Back to basics with October CMS

My brother needed a new simple one-page website for his CV. I usually do my websites in WordPress, but today I wanted to try something new. The content management systems (CMS) I evaluated were:

  • Craftcms
  • contentful
  • Octobercms.com
  • Pagekit
  • Bolt
  • Sitecake
  • Getkirby
  • Bludit

I found a winner: OctoberCMS! It truly is great for developing websites. Not as complicated as most CMS have gotten. Just a simple structure with real files to describe the content of the website. The website is divided into layouts, pages, partials and content. The layout is like the theme. The layout includes partials. When you want a new page (a new url) you add a page. (I skipped using the content type for now since I was making a one-page website). The editor is just simple HTML, (but you can add a proper wysiwyg editor if you want). For more complicated stuff (ecommerce and so on) you can add plugins.

You can check out the website at https://jonathannilsson.com/

Tagged with: ,
Posted in Blog

Appium MQTT backdoor

Appium is generally considered a blackbox testing tool, that is it has no access to the app's methods. Appium acts on the elements accessible by an user.

But what if that is not enough? For example if you want to simulate an incoming notification, a bluetooth device connection, or a crash? For that you need whitebox testing with access to the app's internal methods.


There are ways to do whitebox testing in Android using the espresso driver: https://appiumpro.com/editions/51

There is also a library to add backdoor testing to iOS+Appium: https://github.com/alexmx/Insider

But neither of these solutions work as a backdoor in C# apps, and I am mainly thinking about Android and iOS apps using the Xamarin framework. I also want my backdoor to be callable from Python and Robot Framework. For that I made a backdoor with MQTT messaging.


MQTT broker


Not really necessary for this backdoor to work, but it is a really good tool for testing mobile apps.


Necessary to call the backdoor from if you want to use the code I wrote, but you could implement the backdoor access in any language. You just need to be able to call a MQTT broker.

Robot framework

Only necessary if you want to use it. You could run the tests in python or any other language.

Add testing backdoors to your app

Implement the backdoor in your C# app

Add a handler to the backdoor events:

// Initialize the MQTT backdoor
Task t = Backdoor.Instance.Initialize(mqttHost: "YOUR_MQTT_HOST");

// Handle backdoor events
Backdoor.Instance.BackdoorEvent += HandleBackdoorEvent;
private void HandleBackdoorEvent(object sender, BackdoorEventArgs e)
    // here is where you implement the backdoors
    if (e.Subtopic == "ReceiveNotification")

There is an example app implemented in Xamarin forms in /AppBackdoor/BackdoorExampleApp

Use the backdoor from your tests

There is a python module in appium-mqtt-backdoor\BackdoorAccess\BackdoorAccess

Call it from python like so:

from BackdoorAccess.BackdoorAccess import BackdoorAccess

backdoorAccess = BackdoorAccess(broker_host=MQTT_BROKER_HOST)
backdoorAccess.backdoor('ReceiveNotification', 'Showing popup via backdoor')

I made two examples on how to use the backdoor. One in Robot framwork and one in pure python. Both uses the same python module implementation.

Robot framework example

*** Settings ***
Library            AppiumLibrary
Library            ../BackdoorAccess/BackdoorAccess.py    

*** Variables ***
${Android apk path}         ${CURDIR}/../../AppBackdoor/BackdoorExampleApp/BackdoorExampleApp.Android/bin/Debug/com.companyname.backdoorexampleapp-Signed.apk
${Android package name}     com.companyname.backdoorexampleapp
${iOS app path}             ${CURDIR}/../../AppBackdoor/BackdoorExampleApp/BackdoorExampleApp.iOS/bin/iPhoneSimulator/Release/BackdoorExampleApp.iOS.app
${Apple team id}            

*** Test Cases ***
Test button press and notifications on Android app
    [Tags]  Android
    Open Android example app
    Click button and check that label was updated
    Simulate a notification
	Sleep  2
	Close application

Test button press and notifications on iOS app
    [Tags]  iOS
    Open iOS example app
    Click button and check that label was updated
    Simulate a notification
    Sleep  2
	Close application

*** Keywords ***
Open Android example app
    Open Application    ${APPIUM_SERVER}    platformName=Android    deviceName=Android Emulator    noReset=true    autoGrantPermissions=true  app=${Android apk path}  appPackage=${Android package name}

Open iOS example app
    Open Application    ${APPIUM_SERVER}    platformName=iOS    deviceName=iPhone 8    automationName=XCUITest    noReset=true    platformVersion=13.4    xcodeOrgId=${Apple team id}    xcodeSigningId=iPhone Developer    app=${iOS app path}

Click button and check that label was updated
	Click element  accessibility_id=A button
	Element Should Contain Text  accessibility_id=Number of button clicks  Button was pressed once

Simulate a notification
    Backdoor  ReceiveNotification  Showing popup via backdoor

Python unittest example

import unittest
import os
from appium import webdriver
from BackdoorAccess.BackdoorAccess import BackdoorAccess
import time

script_folder = os.path.dirname(os.path.realpath(__file__))

APPLE_TEAM_ID = 'your team id'

class MyTestCase(unittest.TestCase):
    def test_button_press_and_notifications_on_android(self):

    def test_button_press_and_notifications_on_ios(self):

    def open_android_example_app(self):
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['deviceName'] = 'Android Emulator'
        desired_caps['noReset'] = True
            'app'] = f'{script_folder}/../../AppBackdoor/BackdoorExampleApp/BackdoorExampleApp.Android/bin/Release/com.companyname.backdoorexampleapp-Signed.apk'
        desired_caps['appPackage'] = 'com.companyname.backdoorexampleapp'

        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def open_ios_example_app(self):
        # modify these capabilities to work on your machine
        desired_caps = {}
        desired_caps['platformName'] = 'iOS'
        desired_caps['deviceName'] = 'iPhone 8'
        desired_caps['automationName'] = 'XCUITest'
        desired_caps['noReset'] = True
        desired_caps['platformVersion'] = '13.4'
        desired_caps['xcodeOrgId'] = APPLE_TEAM_ID
        desired_caps['xcodeSigningId'] = 'iPhone Developer'
        desired_caps['app'] = os.path.abspath(f'{script_folder}/../../AppBackdoor/BackdoorExampleApp/BackdoorExampleApp.iOS/bin/iPhoneSimulator/Release/BackdoorExampleApp.iOS.app')

        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def click_button_and_check_that_label_was_updated(self):
        # click button
        button = self.driver.find_element_by_accessibility_id('A button')

        # check that label text was updated
        label = self.driver.find_element_by_accessibility_id('Number of button clicks')
        self.assertEqual('Button was pressed once', label.text)

    def simulate_a_notification(self):
        backdoorAccess = BackdoorAccess(broker_host=MQTT_BROKER_HOST)
        backdoorAccess.backdoor('ReceiveNotification', 'Showing popup via backdoor')

if __name__ == '__main__':


Obviously having a backdoor in your application is a data security issue. Disable all backdoors before shipping the application:

// Initialize the MQTT backdoor
Task t = Backdoor.Instance.Initialize(mqttHost: "YOUR_MQTT_HOST");


sebnil/appium-mqtt-backdoor git repo

Support me creating open source software

Flattr this git repo

Buy Me a Coffee at ko-fi.com

Tagged with: , ,
Posted in Blog

Our game Bananpiren has launched!

After years of inactive development I have decided to release the game I made together with my brother; Bananpiren. It is a game where you control a banana boat in Gothenburg. Your task is to transport as many banana crates as possible. Give it a try!

The game was my first game project in Unity3D. Great fun creating a game, but even a very simple game like this took more time than I would like to admit to finish. Let's see if I ever make a second one. Maybe if this one becomes a great success.

Posted in Bananpiren, Blog, Timeline

Enable dark mode on your website with CSS

Dark mode is getting more and more popular. It is easier on the eyes and especially when working late. Both Windows and MacOS support setting the color scheme to a darker tint, but the websites we visit stay the same. But that might be about to change with a new CSS standard.

I added this CSS code on this website:

/* dark mode */
@media (prefers-color-scheme: dark) {
    background: #111;
    color: #fff;

  #header h1#logo a {
    color: #fff;

What it means is that if the user prefers dark mode, invert the colors and make the background dark, and the text white. It looks like this if you navigate to the site using using a browser that supports this new feature, and if you have dark mode enabled in your OS:

Support for this feature is at the moment quite low. Only the latest versions of Safari and Firefox supports it, but it looks like it will make the standard so more or less every browser will support it in a while.

Posted in Blog

Black bean stew with rice


  • Olive oil
  • garlic
  • chopped onion
  • green paprika
  • sweet paprika spice powder
  • salt
  • cumin powder
  • oregano
  • 2 cans of black beans
  • black pepper
  • boiled rice
  • coriander leaves (if available)
  • chopped chilli/jalepeno


  • Chop garlic, onion, paprika
  • heat oil
  • add garlic and chopped onion and sautee until onions are a bit brown
  • add paprika and sautee
  • add paprika powder, salt, cumin powder, oregano, black pepper and sautee for a few minutes
  • add drained black beans and water
  • let it boil for some time
  • serve with boiled rice
Posted in Blog

Pesto pasta


  • Pasta
  • Pesto (either make your own or buy a small jar)
  • Pine nuts
  • Chili
  • Basil for decoration
  • Oil
  • Salad on the side


  1. Cook pasta
  2. Mix with pesto (how to make pesto instructions below)
  3. Pine nuts roasted and put on top
  4. Chili in oil
  5. Basil for decoration
  6. Any salad on the side.
Posted in Blog

Chia pudding (dessert)

Time: 10 minutes to prepare and 4 hours in fridge


  • 1 can coconut milk (or any other milk)
  • 4 tablespoons chia seeds
  • honey
  • vanilla extract
  • mixed berries of choice


  1. In a container, combine the milk, honey, chia seeds and vanilla extract. Stir thoroughly until combined well.
  2. Pour mixture into a jar and refrigerate until it reaches the desired thickness (about 4 hours)
  3. Serve pudding with mixed berries sprinkled on top.
Posted in Blog

Aglio Olio (oily spaghetti and chili)


  • olive oil
  • sliced or crushed garlic
  • chilli flakes
  • salt
  • parsley (optional)
  • sundried tomatoes (optional)
  • boiled spagetti
  • reserved pasta water or regular water
  • parmesan cheese
  • salad


  1. Heat oil in a pan
  2. add garlic and sautee for a few seconds. Don’t let garlic get crispy or burn
  3. add chili flakes
  4. add ½ cup pasta water, salt and chili flakes
  5. let it almost evaporate
  6. add pasta and parsley and mix
  7. grate parmesan
  8. eat with salad
Posted in Blog

Tofu Rice dill

Quantity: 2 servings
Time: 30 minutes


  • Tofu
  • Turmeric
  • Olive oil
  • Salt
  • Pepper
  • Rice 1 cup
  • Water 1 ¾ cups
  • Dill ½ cup
  • Peas
  • Salt
  • Yogurt


  1. Fry tofu with turmeric, oil, salt and pepper.
  2. For the rice, cook rice with dried dill and peas. Add salt and olive oil.
  3. Optionally serve with yogurt on the side.
Posted in Blog

One-Pan Mexican Quinoa

5 servings
30 minutes


  • quinoa: 1,25 cups,
  • Or quinoa+Rice: 2 cups
  • diced tomatoes (spicy if you’d like): 1 can,
  • black beans: 1 can,
  • corn: 1 can,
  • lime juice: 1 tablespoon,
  • Or lime: 1
  • avocado: 1,
  • chili powder
  • black pepper
  • salt
  • garlic powder
  • cayenne pepper



  1. Big pan. Add quinoa, 2.25 cups of water, tomatoes (don’t drain)
  2. Bring it to boil and them simmer for 12-18 minutes until the quinoa pops open.
  3. Drain black beans and corn and put into separate bowl. Add lime juice.
  4. Dice avocado
  5. When quinoa is done, add bowl and spices to taste
  6. Add avocado as topping
Posted in Blog