Serenity Cucumber4 Environment URL on Page Objects not working - cucumber

Why does this not work?
When I run the feature file as "Run as Cucumber Feature" I get an error
java.lang.AssertionError: Undefined default URL for page object PageObject
Page Object
#DefaultUrl("page:register.page")
public class AccountCreationPage extends PageObject {
...
}
Config File (serenity.config)
environments {
local {
webdriver.base.url = "https://localhost"
}
demo {
webdriver.base.url = "https://demo.example.com"
}
prod {
webdriver.base.url = "https://example.com"
}
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}
https://johnfergusonsmart.com/environment-specific-configuration-in-serenity-bdd/
shows the use of #DefaultUrl("page:register.page")
Serenity-Cucumber4. Java. Eclipse.

the config file is required to have default as an entry 🤦
environments {
default {
webdriver.base.url = "https://localhost"
}
...
all {
home.page = "#{webdriver.base.url}"
register.page = "#{webdriver.base.url}/register"
}
}

Related

Groovy ConfigSlurper is only partially building the structure when parsed

I am building a library for myself and using ConfigSlurper to parse a config.groovy file, and other config sources into an aggregated ConfigObject that I am using Micronaught compile time IOC to inject
#Bean
#Named('config')
ConfigObject config () {
Map envMap = [:]
def sysProps = System.getenv()
if (System.getProperty("env") ) {
envMap = System.getenv().findResult { it.key?.toLowerCase().contains "env" }.collect { [(it.key?.toLowerCase().substring(0, 2)): it.value.toLowerCase()] }
} else
envMap.get ('env', "development")
def env = envMap.get('env')
def resourcePath = "src${File.separatorChar}${env =="test" ?: "main"}${File.separatorChar}resources${File.separatorChar}"
ConfigObject config = new ConfigSlurper().parse(new File("${resourcePath}ApplicationConfig.groovy").text /*.toURI().toURL()*/)
config.put('systemProperties', sysProps)
config.putAll(envMap)
config.put('projectPath', System.getProperty("user.dir"))
config.put('resourcesPath', resourcePath.toString())
File resourceDirectory = new File ("${System.getProperty("user.dir")}$File.separatorChar$resourcePath")
FilenameFilter filter = {file, name -> name.matches(~/^.*properties$/) }
List propsFiles = resourceDirectory.listFiles (filter)
filter = {file, name -> name.matches(~/^.*yaml$/) }
List yamlFiles = resourceDirectory.listFiles (filter)
propsFiles.each {file ->
Properties prop = new Properties()
prop.load(new FileInputStream (file) )
Map propsMap = [:]
for (key in prop.stringPropertyNames()) {
propsMap.put(key, prop.getProperty(key))
}
config.putAll(propsMap)
}
yamlFiles.each {file ->
def yamlConfig = new YamlSlurper().parseText(file.text)
config.putAll(yamlConfig)
}
config
}
the resources/applicationConfig.groovy file looks like this
framework {
environments {
development {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
test {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
production {
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
The code parses the groovy file but when I look at what in the configObject, its created the tope level framework map entry - but the lower levels are not there.
calling configObject.framework in code returns the object but it is of size() == 0!
I don't understand why the rest of the structure is not getting built.
Can any one advise why the internal structure is not being parsed and built.
Can anyone suggest what I have done wrong ?
I have just done a stripped back version like this
def configText = """
framework {
environments {
development {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
test {
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
production {
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
"""
ConfigObject conf = new ConfigSlurper().parse(configText)
assert conf.framework?.environments?.size() == 3
where the error shows this
Caught: Assertion failed:
assert conf.framework?.environments?.size() == 3
| | | | |
| | [:] 0 false
| ['environments':[:]]
['framework':['environments':[:]]]
Assertion failed:
assert conf.framework?.environments?.size() == 3
| | | | |
| | [:] 0 false
| ['environments':[:]]
['framework':['environments':[:]]]
at scripts.configSlurperTest.run(configSlurperTest.groovy:33)
at
The environments section when parsed by configslurper is conditional to the environment you pass to the constructor of ConfigSlurper itself.
Lets say you want the development config to be the default, but then you want to override this when run in test or production, you would do the following:
def configText = """
framework {
// defaults
mode = 'development'
server = "local" // choice of {local|clustered}
vertxOptions {
}
environments {
// test settings
test {
mode = 'testing'
server = "local" // choice of {local|clustered}
vertxOptions {
}
}
// production settings
production {
mode = 'live!'
server = "clustered" // choice of {local|clustered}
vertxOptions {
}
}
}
}
"""
// Default values
assert new ConfigSlurper().parse(configText).framework.mode == 'development'
// Test values
assert new ConfigSlurper('test').parse(configText).framework.mode == 'testing'
// Production values
assert new ConfigSlurper('production').parse(configText).framework.mode == 'live!'

GEB: set default environment?

I declared a few environments in GebConfig via environments {} closure.
And if I specify -Dgeb.env in command line, everything works perfectly.
But when I start a single test for debugging purposes, I don't want to explicitly pass any additional environment variables.
What is the way to define the environment to be used by GEB as a default?
Just define a default driver outside of the environments My Geb config looks like this:
driver = {
new HtmlUnitDriver(true)
}
environments {
html_unit {
driver = {
new HtmlUnitDriver(true)
}
}
phantomjs {
driver = {
WebDriverManager.phantomjs().version("2.1.1").setup()
def pjsDriver = new PhantomJSDriver()
pjsDriver.manage().window().size = new Dimension(1024, 768)
pjsDriver
}
}
chrome {
driver = {
// (...)
}
}
chrome_headless {
System.setProperty("webdriver.chrome.logfile", "chromedriver.log")
System.setProperty("webdriver.chrome.verboseLogging", "true")
driver = {
// (...)
}
}
firefox {
driver = {
// (...)
}
}
ie {
driver = {
// (...)
}
}
edge {
driver = {
// (...)
}
}
opera {
driver = {
// (...)
}
}
win_app {
driver = {
// (...)
}
}
}

Overwrite backend template in bolt.cms

I am trying to overwrite a template file located in vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig (I want to replace the "block selection" dropdown). Regarding to #1173, #1269, #5588, #3768 and #5102 this is not supported by default so I have to write a extension for this. So I tried this:
BackendBlockSelectionExtension:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Bolt\Extension\SimpleExtension;
class BackendBlockSelectionExtension extends SimpleExtension
{
public function getServiceProviders()
{
return [
$this,
new BackendBlockSelectionProvider(),
];
}
}
BackendBlockSelectionProvider:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Silex\ServiceProviderInterface;
class BackendBlockSelectionProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$side = $app['config']->getWhichEnd();
if ($side == 'backend') {
$path = __DIR__ . '/App/templates/Backend';
$filesystem = $app['filesystem'];
$filesystem->mountFilesystem('bolt', new Filesystem(new Local($path)));
$app['twig.loader.bolt_filesystem'] = $app->share(
$app->extend(
'twig.loader.bolt_filesystem',
function ($filesystem, $app) {
$path = __DIR__ . 'src/App/templates/Backend/';
$filesystem->prependPath($path, 'bolt');
return $filesystem;
}
)
);
}
}
public function boot(Application $app)
{
}
}
This seems to do the job, but I got an error I don't understand at all: The "bolt://app/theme_defaults" directory does not exist.
So my final question is: Does anyone have some example code how to overwrite/modify vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig without touching the vendor folder?
This should be much simplier than this.
In your extension class overwrite protected function registerTwigPaths() function like this:
protected function registerTwigPaths()
{
if ($this->getEnd() == 'backend') {
return [
'view' => ['position' => 'prepend', 'namespace' => 'bolt']
];
}
return [];
}
private function getEnd()
{
$backendPrefix = $this->container['config']->get('general/branding/path');
$end = $this->container['config']->getWhichEnd();
switch ($end) {
case 'backend':
return 'backend';
case 'async':
// we have async request
// if the request begin with "/admin" (general/branding/path)
// it has been made on backend else somewhere else
$url = '/' . ltrim($_SERVER['REQUEST_URI'], $this->container['paths']['root']);
$adminUrl = '/' . trim($backendPrefix, '/');
if (strpos($url, $adminUrl) === 0) {
return 'backend';
}
default:
return $end;
}
}
Now you can crete a view directory in your extensions directory in which you can define templates in structure like in Bolt's default. I would start with copy and overwrite.

How to read Html files by using XmlReader

I want to read HTML file by using XMLReader. So I wrote some codes, but it throws only XmlException. So please give me any suggestion about how to read the HTML file (and tags) line by line using C#.
public class HtmlReader
{
public List<HtmlDocument> Read(string path)
{
List<HtmlDocument> html = new List<HtmlDocument>();
HtmlDocument h1 = new HtmlDocument();
using (XmlReader reader = XmlReader.Create(path.ToString()))
{
try
{
while (reader.Read())
{
if (reader.IsStartElement())
{
if (reader.Name == "title" || reader.Name == "body")
{
switch (reader.Name)
{
case "title":
if (reader.Read())
{
h1.Title = reader.Value.Trim();
}
break;
case "body":
if (reader.Read())
{
}
break;
}
}
}
}
}
catch(XmlException)
{
}
}
return html;
}
}
}
class Program
{
static void Main(string[] args)
{
HtmlReader readerObject = new HtmlReader();
List<HtmlDocument> employeeCollection = readerObject.Read("E:/workoutsPrograms/ConsoleApplication4/Table.html");
}
}
I tried this, but I was not able to read the Html tags line by line. Apart from my expectation, it throws only Exception.
I find the answer for above question. Following codes you can use.
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
settings.IgnoreWhitespace = true;
XmlRederSettings is enabled set features of XmlReader. In that Html file have DOCTYPe, For that avoid we want use the Dtdprocessing.Ignore.

Custom init on test/development mode in Grails

I want to run specific login in BootStrap class depending on development or test mode is currently used.
How can I do this?
From the documentation:
class Bootstrap {
def init = { ServletContext ctx ->
environments {
production {
// prod initialization
}
test {
// test initialization
}
development {
// dev initialization
}
}
}
...
}
import grails.util.Environment
class BootStrap {
def init = { servletContext ->
def currentEnv = Environment.current
if (currentEnv == Environment.DEVELOPMENT) {
// do custom init for dev here
} else if (currentEnv == Environment.TEST) {
// do custom init for test here
} else if (currentEnv == Environment.PRODUCTION) {
// do custom init for prod here
}
}
def destroy = {
}
}
from the official docs
Programmatic Environment Detection
Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the GrailsUtil class:
import grails.util.GrailsUtil
...
switch(GrailsUtil.environment) {
case "development":
configureForDevelopment()
break
case "production":
configureForProduction()
break

Resources