I have this feature file :
Given I launch google using chrome as browser
When I search by kotlin
Then I will see 32 results per page
where my properties file has the content :
e1=www.google.com
field= kotlin
nr=32
However, the third steps from my feature file appears as if they aren't implemented : https://www.screencast.com/t/fP9vjdToSI
I have implemented the steps in a kotlin class :
init {
Given("^I launch \"(.*)\" using chrome as browser$") { element: String ->
// load the properties file
// prop.load(file)
prop.load(StepsDefinition::class.java!!.getClassLoader()
.getResourceAsStream("application-test.properties"))
// set the properties
prop.getProperty("el1")
val element= prop.getProperty("el1")
println(prop.getProperty("el1"))
driver.get(element)
When("^I search by \"(.*)\"$") { field: String ->
val button = driver.findElement(By.xpath("//input[#value=\"" + field+ "\"]" +
"| //button[contains(text(),\"" + field+ "\")]"))
button.isDisplayed
button.click()
}
Then("^I see \"(.*)\" results per page") { nr: String ->
val wait = WebDriverWait(driver, 10)
Assert.assertTrue(driver.getTitle().contains(nr))
}
Can someone please help me?
Thanks.
I don't have cucumber currently set up on my machine so I can't really verify what I'm saying, however I'd say it's just a mismatch between the step definition and the step in the feature.
Your step definition expects the keyword to be wrapped in quotes, while in your feature file you're not using any quotes. The same should apply to the When step (same error) and to the Then step, where you put an extra will.
Related
In my android project I got very intericting task
My company wants to hide all mintions about her in code (variables names, packages and etc)
But only for one flavour, so I cannot do it once for all project.
My first idea, was writing a simple gradle task, that will replace all strings that fit in code, but in this case package names will remain unchanged.
Secondly, since we have ci on Jenkins, I thought about jenkins script, that will rename all files and its content, if it has keyword. But this solution looks very bulky for me.
Maybe there is another, elegant way?
Replacing the package name/variable names blindly seems a bit risky, as it could replace other overlapping strings as well, which may lead to various issues. Assuming your package name is unique and you don't have any overlapping names and it doesn't result in any directory name changes, you can use different methods to replace the package name.
Option 1
Using shell to achieve this. There are plenty of different ways to do this, following is one option with grep and sed
sh '''
grep -rl ${PACKAGE_NAME_TO_REPLACE} ${DESTINATION_DIR} | xargs sed -i "s&${PACKAGE_NAME_TO_REPLACE}&${PACKAGE_NAME_NEW}&g"
'''
You can take a look at this and this to understand different methods you can use.
Option 2
If you want a more controlled approach, you can achieve this with some groovy code as well. Simply run the following within your Pipeline.
def dirToSearchIn = "/where/to/replace"
// Change the content on specific files. You can improve the regex pattern below to fine-tune it. With the following pattern only files with extensions .java and .md will be changed.
def filterFilePattern = ~/.*\.java|.*\.md$/
def oldString = "replaceme"
def newString = "newme"
new File(dirToSearchIn).traverse(type: groovy.io.FileType.FILES, nameFilter: filterFilePattern) { file ->
println "Processing file: " + file.getPath()
def fileContent = file.text;
if (fileContent.contains(oldString)) {
println "Replacing the content of the file: " + file.getPath()
file.write(fileContent.replaceAll(oldString, newString));
} else {
println "Skipping file: " + file.getPath()
}
}
Adding something like the following to your top-level build.gradle file should do the trick (assuming your company is called “ACME” and you rather want it to be called “foobar”):
def duplicateProjDirName = 'duplicateProj'
def duplicateProjDir = project.layout.buildDirectory.dir(duplicateProjDirName)
def duplicateProj = tasks.register('createDuplicateProject', Copy) {
enabled = (projectDir.name != duplicateProjDirName)
from(project.layout.projectDirectory)
into(duplicateProjDir)
exclude('build', '.gradle')
def acmePattern = /(?i)acme/
def newCompanyName = 'foobar'
eachFile { it.path = it.sourcePath.replaceAll(acmePattern, newCompanyName) }
filter { it.replaceAll(acmePattern, newCompanyName) }
includeEmptyDirs = false
}
def duplicateBuild = tasks.register('buildDuplicateProject', GradleBuild) {
enabled = (projectDir.name != duplicateProjDirName)
dependsOn(duplicateProj)
dir = duplicateProjDir
tasks = ['build']
}
tasks.named('build').configure {
dependsOn(duplicateBuild)
}
This essentially adds two tasks to the project:
createDuplicateProject duplicates the project under build/duplicateProj/ with all mentions of “ACME” replaced with “foobar”. It also takes care of renaming files/directories (in contrast to the solutions in other answers so far).
buildDuplicateProject builds the duplicate project.
While this may work in basic scenarios (I’ve successfully tested it with a small dummy Java project and Gradle 7.6), there are some edge cases to think about:
There may be dependencies (libraries, services, etc.) which contain the company name and which won’t work anymore after they’ve been renamed.
This way of replacing
may not work well for binary files.
does not catch occurrences in code such as "AC" + "ME".
case-insensitively may lead to weird-looking names that don’t follow common conventions. In the worst case, this could lead to different behavior, too.
There may be downstream projects which depend on package names or the like that are renamed here.
Your company may not only be identifiable by name, e.g., there may also be logos in image files, etc.
and probably others
Android Platform
i use below code to generate and share the link in Facebook etc, and click it, it has record in " Summary ", but not show in Quick Link Dashboard.
val lp = LinkProperties()
.addControlParameter("\$deeplink_path","https://www.google.com")
val buo = BranchUniversalObject()
.setCanonicalIdentifier("item/abcd")
.setTitle("Hellow Title")
.setContentDescription("Hello Description")
.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
.setLocalIndexMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
buo.generateShortUrl(
activity, lp
) { url, error ->
if (error == null) {
// share intent
} else {
Logger.e("error: ${error.message}")
}
}
Using the code, this cannot show in the Quick Link Dashboard.
About the doc, it need add two params "type:2" and "$marketing_title", i set it to LinkProperties:
lp.addControlParameter("type", "2")
.addControlParameter("\$marketing_title", "android _test")
Or: BranchUniversalObject:
buo.setContentMetadata(ContentMetadata().addCustomMetadata("type", "2"))
.setContentMetadata(ContentMetadata().addCustomMetadata("\$marketing_title","android"))
But it not work, so, how to solve?
Thanks!
By default, your SDK-created links will not be visible on the Quick Links Dashboard. The specification of passing type:2 and setting a marketing title in the request payload is limited to API-created links only.
Understanding that you'd want to check the conversions, it is highly recommended to tag these branch links (e.g. channel = API/campaign=Promo) so that you can segment your data to see all installs/clicks from links created via the SDK on the Branch Dashboard Sources/Summary section.
According to GitHub sample project and Tealium's documentation for Kotlin I created such TealiumHelper:
object TealiumHelper {
fun init(application: Application) {
val tealiumConfig = TealiumConfig(
application,
accountName = BuildConfig.TEALIUM_ACCOUNT_NAME,
profileName = BuildConfig.TEALIUM_PROFILE_NAME,
environment = BuildConfig.TEALIUM_ENVIRONMENT
)
// Display logs only for DEV
Logger.Companion.logLevel = BuildConfig.TEALIUM_LOGLEVEL
// Make it start working
Tealium.create(BuildConfig.TEALIUM_INSTANCE, tealiumConfig)
}
fun trackEvent(name: String, data: Map<String, Any>? = null) {
val eventDispatch = TealiumEvent(name, data)
Tealium[BuildConfig.TEALIUM_INSTANCE]?.track(eventDispatch)
}
fun trackView(name: String, data: Map<String, Any>? = null) {
val viewDispatch = TealiumView(name, data)
Tealium[BuildConfig.TEALIUM_INSTANCE]?.track(viewDispatch)
}
}
I get logs by Tealium so it should be working fine.
2021-05-17 14:28:56.694 22812-22894/xxx.xxx.xxx D/Tealium-1.2.2: Dispatch(fc5c0) - Ready - {tealium_event_type=view, tealium_event=XXX ...}
But after I call trackView or trackEvent, my events don't go to server.
There is also additional log infor which I don't know what does it mean. Documentation doesn't say much about it:
2021-05-17 14:28:59.352 22812-22894/xxx.xxx.xxx I/Tealium-1.2.2: Asset not found (tealium-settings.json)
How could I fix it? What does Asset not found mean?
#deadfish I manage the mobile team here at Tealium, so I can point you in the right direction. You can safely ignore the Asset Not Found log - this just indicates that no local settings file was found, so by default, the remote settings will be used. We'll look at addressing this to make the log message a little more helpful. There are a couple of things that might cause data not to be sent. Firstly, I can't see any Dispatchers specified in your TealiumConfig object. As specified in the docs, you need to add either the TagManagement or Collect dispatcher, which are the modules that send the data from the device. The Collect module sends data to the server-side platform (I think this is what you need), while the TagManagement module processes the data client-side using JavaScript. Please feel free to get in touch with our support team or contact us by raising an issue on our GitHub repo if you need further personalized support.
I am learning logging in android code using android studio and emulator
I found that the following command shows a traceback with hyperlink to the code location
Log.d("TAG", "Message with stack trace info", new Throwable());
the image of logcat with hyperlink is
How can i create only the hyperlink part in my log message, without any traceback output
Try this, for example:
import android.util.Log;
public class Logger {
public static void log(String tag, String message) {
String caller = getCallerInfo(new Throwable().getStackTrace());
Log.d(tag, message + caller);
}
private static String getCallerInfo(StackTraceElement[] stacks) {
if (stacks == null || stacks.length < 1) {
return "";
}
StackTraceElement stack = stacks[1];
return String.format(" (%s:%s)", stack.getFileName(), stack.getLineNumber());
}
}
And call it from any where in your code
Logger.log("Manowar", "Today is the good day to die");
As of now the answer by #Cao Mạnh Quang was not giving me the Hyperlink.
The specific String format required for it's generation is this:
return String.format(" %s(%s:%s)", traceE.getClassName(), traceE.getFileName(), traceE.getLineNumber());
which is just the same as:
return stackTraceElement.toString();
so you may as well just do that.
Nothing was working for me...
My guess is that...
This hyperlink is generated by a preconfigured String specification format.
this format follows the className + "(" + fileName + ":" + lineNumber + ")"
If any of those parameters are missing, the hyperlink will not be generated.
There are a couple questions that arise from this:
Is this specification hard coded as a consensus of each LogCat display (IDE side interacts directly with String)
OR
Is this specification hardcoded into the Java code itself? (Java side interprets String generates hyperlink signal + IDE side interprets hyperlink signal and generates it)
The difference between which of these options is the one, would imply whether hyperlink generation is possible simply by changing the required configuration for the Logcat to generate the link either at IDE config level... OR at Java level.
Maybe it is not possible, and this configuration format cannot be changed....
Btw I am sure there must be some super hacky way to achieve this, maybe a way not so intuitive... or maybe it just requires some digging on the IDE config options...
With normal installed apps it's possible to use the technique of Deep Linking in order to not only open a specific application from an URL but also to redirect it to a specific section/function such as a specific Facebook post or specific coordinates on a map.
Since I've read that with Instant Apps this won't be possible because links already point to the specific module to download and run, how would it be possible to access not only the said module but also pass it some parameters?
For example:
This is the link from which the view-only module of my map application will be downloaded: "www.myinstantappexample.com/onlyviewmap"
If I want it to point to a specific set of coordinates how would the link be composed?
Will it be like this: "www.myinstantappexample.com/onlyviewmap/?x=0.000&y=0.000" ?
From what I've been able to find google doesn't cover this aspect and I really can't wrap my head around it.
If I want it to point to a specific set of coordinates how would the link be composed?
It's up to you how to include any additional info in the URL. It could be via URL parameters or in the path itself. Eg.
https://www.myinstantappexample.com/location/2/user/5
https://www.myinstantappexample.com/onlyviewmap/?x=1.2&y=3.4
You then parse the URL in the receiving Activity. The Uri class includes a number of helper methods such as getQueryParameter() and getPathSegments() to make this easier.
For example, to parse this URL:
https://www.myinstantappexample.com/onlyviewmap/?x=1.2&y=3.4
You would do something like this in your Activity:
Uri uri = getIntent().getData();
String x;
String y;
if (uri != null) {
x = uri.getQueryParameter("x"); // x = "1.2"
y = uri.getQueryParameter("y"); // y = "3.4"
}
if (x != null && y != null) {
// do something interesting with x and y
}
Instant Apps and Deep Linking
Instant Apps rely on App Links to work, and App Links are just one type of deep link. So deep linking is still possible for Instant Apps, and is in fact absolutely critical to how they function. However, URI scheme deep linking (which is still very prevalent in Android apps) is not supported.
The difference between a regular app and an Instant App is that the device will only load a single Activity in response to the App Link the user clicks, instead of needing to download the full package through the Play Store. It's a more seamless experience for the user, but the underlying technology works the same way.
Passing Custom Parameters
If the user clicks an App Links-enabled URL like http://www.myinstantappexample.com/onlyviewmap/?x=0.000&y=0.000, you will get that entire string back inside the app after it opens. You'll have to parse out the x and y variables yourself, but they will be available to you. Something like this:
Uri data = this.getIntent().getData();
if (data != null && data.isHierarchical()) {
String uri = this.getIntent().getDataString();
Log.i("MyApp", "Deep link clicked " + uri);
}
You'll just need to manipulate the uri value to find what you need.
Alternative Approach to Custom Parameters
Alternatively, you can use Branch.io (full disclosure: I'm on the Branch team) to power your links. We have full support for Instant Apps, and this allows you to work with a much more friendly data format. We let you create links like this, to control every part of the behavior:
branch.link({
tags: [ 'tag1', 'tag2' ],
channel: 'facebook',
feature: 'dashboard',
stage: 'new user',
data: {
x: '0.000',
y: '0.000',
'$desktop_url': 'http://myappwebsite.com',
'$ios_url': 'http://myappwebsite.com/ios',
'$ipad_url': 'http://myappwebsite.com/ipad',
'$android_url': 'http://myappwebsite.com/android',
'$og_app_id': '12345',
'$og_title': 'My App',
'$og_description': 'My app\'s description.',
'$og_image_url': 'http://myappwebsite.com/image.png'
}
}, function(err, link) {
console.log(err, link);
});
In return you get a URL like http://myappname.app.link/iDdkwZR5hx, and then inside the app after the link is clicked, you'll get something that looks like this:
{
tags: [ 'tag1', 'tag2' ],
channel: 'facebook',
feature: 'dashboard',
stage: 'new user',
data: {
x: '0.000',
y: '0.000'
}
}
In order to do that, you have to use the "app links assistant" in
Tools->App Links Assistant
Then check your links and, in the Path selector, check that the "pathPrefix" option is selected.
Then at the bottom of the OnCreate method of your activity (which is related to the link you recently edited) add this code:
Intent appLinkIntent = getIntent();
String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData();
// then use appLinkData.getQueryParameter("YourParameter")
You can test and debug this, using the "editConfigurations" option, just open that window and edit your instantApp module (the one launched with the Link you recently edited) and in the URL field add the URL parameters that you need. (then just run that module :D )
Hope this to be helpful.