Giter Club home page Giter Club logo

cordova-simulate's Introduction

Cordova-Simulate Build Status

Simulates your Apache Cordova application in the browser.

Table of Contents

Installation

npm install -g cordova-simulate

Usage

CLI

From the command line anywhere within a Cordova project, enter the following:

simulate [<platform>] [--device=<DEVICE_ID>] [--corsproxy=<true|false>] [--dir=<DIR>] [--livereload=<true|false>] [--port=<PORT>] [--forceprepare=<true|false>] [--simhostui=<SIM_HOST_UI_MODULE_PATH>] [--simulationpath=<SIMULATION_PATH>] [--target=<BROWSER>] [--lang=<LANG>] [--theme=<THEME>] [--middleware=<MIDDLEWARE_PATH>] [--generateids=<true|false>] [--spaurlrewrites=<true|false>] [--showbrowser=<true|false>] [--chromiumpath=<CHROMIUM_PATH>]

See parameters description in the API section.

API

Use require('cordova-simulate') to launch a simulation via the API:

var simulate = require('cordova-simulate');
simulate(opts);

Where opts is an object with the following properties (all optional):

  • platform - any Cordova platform that has been added to your project. Defaults to browser.
  • device - specify the id of a device to start with instead of a platform (the platform will be determined by the device). Supported android devices are Nexus4, Nexus6, Nexus7, Nexus10, OptimusL70, G5, GalaxyNote7 and GalaxyS5. Supported ios devices are iPhone4, iPhone5, iPhone6, iPhone6Plus, iPad and iPadPro. Supported windows devices are Lumia930, Lumia950 and SurfacePro. Supported generic devices (which will use the browser platform) are Generic320x480, Generic320x568, Generic360x640, Generic384x640, Generic412x732, Generic768x1024, Generic800x1280 and Generic1920x1080.
  • target - the name of the browser to launch your app in. Can be any of the following: default, chrome, edge, firefox, opera, safari, chromium.
  • port - the desired port for the server to use. Defaults to 8000.
  • lang - the language to display in the interface (does not impact console output). Supported values (case-insensitive) are cs (Czech), de (German), es (Spanish), fr (French), it (Italian), ja (Japanese), ko (Korean), pl (Polish), pt (Portuguese), ru (Russian), tr (Turkish), zh-Hans (Simplified Chinese) and zh-Hant (Traditional Chinese). Additional tags are ignored (for example, de-DE is treated as de).
  • dir - the directory to launch from (where it should look for a Cordova project). Defaults to cwd.
  • simhostui - the directory containing the UI specific files of the simulation host. Defaults to the bundled simulation host files, found in src/sim-host/ui.
  • livereload - a boolean. Set to false to disable live reload. Defaults to true.
  • forceprepare - a boolean. Set to true to force a cordova prepare whenever a file changes during live reload. If this is false, the server will simply copy the changed file to the platform rather than doing a cordova prepare. Ignored if live reload is disabled. Defaults to false.
  • corsproxy - boolean indicating if XMLHttpRequest is proxied through the simulate server. This is useful for working around CORS issues at development time. Defaults to true.
  • touchevents - a boolean. Set to false to disable the simulation of touch events in App-Host. Defaults to true.
  • simulationpath - the directory where temporary simulation files are hosted. Defaults to projectRoot/simulate.
  • simhosttitle - specifies the title of the simulation window. Defaults to Plugin Simulation.
  • middleware - a path that points to express middleware. This can be used to write custom plugins that require the full power of NodeJS.
  • generateids - a boolean that generates unique ids for simulated devices at startup. Defaults to false.
  • livereloaddelay - the delay in milliseconds between saving of a modified file and the application page reloading. You can try to increase the delay in case the simulator server crashes while frequent page reloading. Defaults to 200ms.
  • spaurlrewrites - a boolean. Set to true to fix page refreshing in case the default application URL (/index.html) in the browser was changed by the router in single page applications. Defaults to false.
  • showbrowser - a boolean. Set to true to launch browsers when simulation starts. Defaults to true.
  • chromiumpath - a path that points to Chromium executable file. Required when using Chromium as target on win32.

Use launchBrowser to open target browser with specific url:

require('cordova-simulate').launchBrowser(target, url);
  • target - which browser you want to open, like Chrome, Edge, Firefox, Opera, Safari, Chromium.
  • url - specific website url you want to load.

What it does

Calling simulate() will launch your app in the browser, and open a second browser window displaying UI (the simulation host) that allows you to configure how plugins in your app respond.

Features

  • Allows the user to configure plugin simulation through a UI.
  • Launches the application in a separate browser window so that it's not launched within an iFrame, to ease up debugging.
  • Allows user to persist the settings for a plug-in response.
  • Allows plugins to customize their own UI.
  • Reloads the simulated app as the user makes changes to source files.

Note for live reload: Changes to files such as images, stylesheets and other resources are propagated to the running app without a full page reload. Other changes, such as those to scripts and HTML files, trigger a full page reload.

Supported plugins

This preview version currently includes built-in support for the following Cordova plugins, some of them are deprecated that not being maintained and updated by official:

Simulate in Docker container

Cordova-simulate support cordova application simulation in Docker container, here is the example as below:

  1. Follow the VS Code official documentation to setup your environment and install related extensions(Remote Development is recommended) to use a remote development approach.

  2. In the local react-native project, add Dev Container configure folder and files:

    .devcontainer
      -devcontainer.json
      -Dockerfile
    
  3. Сreate Dockerfile extending your image. For example you can use the following Dockerfile:

    FROM mcr.microsoft.com/devcontainers/base:jammy
    
    RUN npm install -g cordova cordova-simulate
    
  4. Configure your devcontainer.json file as needed. Below is a sample configuration:

    {
      "name": "Cordova Container",
    
      // Sets the run context to one level up instead of the .devcontainer folder.
      "context": "..",
    
      // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
      "dockerFile": "Dockerfile",
    }
  5. Open Command Palette and run the following command Dev Containers: Open Folder in Container to reopen your project in a container

  6. Install supported browser in container and execute simulate.

Adding simulation support to plugins

It also allows for plugins to define their own UI. To add simulation support to a plugin, follow these steps:

  1. Clone this repository (git clone https://github.com/microsoft/cordova-simulate.git), as it contains useful example code (see src/plugins).
  2. Add your plugin UI code to your plugin in src/simulation. Follow the file naming conventions seen in the built-in plugins.

Detailed steps

In your plugin project, add a simulation folder under src, then add any of the following files:

sim-host-panels.html
sim-host-dialogs.html
sim-host.js
sim-host-handlers.js
app-host.js
app-host-handlers.js
app-host-clobbers.js

Simulation Host Files

sim-host-panels.html

This defines panels that will appear in the simulation host UI. At the top level, it should contain one or more cordova-panel elements. The cordova-panel element should have an id which is unique to the plugin (so the plugin name is one possibility, or the shortened version for common plugins (like just camera instead of cordova-plugin-camera). It should also have a caption attribute which defines the caption of the panel.

The contents of the cordova-panel element can be regular HTML, or the various custom elements which are supported (see the existing plugin files for more details).

This file shouldn't contain any JavaScript (including inline event handlers), nor should it link any JavaScript files. Any JavaScript required can be provided in the standard JavaScript files described below, or in additional JavaScript files that can be included using require().

sim-host-dialogs.html

This defines any dialogs that will be used (dialogs are simple modal popups - such as used for the Camera plugin). At the top level it should contain one or more cordova-dialog elements. Each of these must have id and caption attributes (as for sim-host-panels.html). The id will be used in calls to dialog.showDialog() and dialog.hideDialog() (see cordova-simulate/src/plugins/cordova-plugin-camera/sim-host.js for example code).

Other rules for this file are the same as for sim-host-panels.html.

sim-host.js

This file should contain code to initialize your UI. For example - attach event handlers, populate lists etc. It should set module.exports to one of the following:

  1. An object with an initialize method, like this:
module.exports = {
    initialize: function () {
        // Your initialization code here.
    }
};
  1. A function that returns an object with an initialize method. This function will be passed a single parameter - messages - which is a plugin messaging object that can be used to communicate between sim-host and app-host. This form is used when the plugin requires that messages object - otherwise the simple form can be used. For example:
module.exports = function (messages) {
    return {
        initialize: function () {
            // Your initialization code here.
        }
    };
};

In both cases, the code currently executes in the context of the overall simulation host HTML document. You can use getElementById() or querySelector() etc to reference elements in your panel to attach events etc. In the future, this will change and there will be a well defined, limited, asynchronous API for manipulating elements in your simulation UI.

sim-host-handlers.js

This file defines handlers for plugin exec calls. It should return an object in the following form:

{
    service1: {
        action1: function (success, error, args) {
            // exec handler
        },
        action2: function (success, error, args) {
            // exec handler
        }
    },
    service2: {
        action1: function (success, error, args) {
            // exec handler
        },
        action2: function (success, error, args) {
            // exec handler
        }
    }
}

It can define handlers for any number of service/action combinations. As for sim-host.js, it can return the object either by;

  1. Setting module.exports to this object.
  2. Setting module.exports to a function that returns this object (in which case the messages parameter will be passed to that function).

App Host Files

app-host.js

This file is injected into the app itself (as part of a single, combined, app-host.js file). Typically, it would contain code to respond to messages from sim-host code, and as such module.exports should be set a function that takes a single messages parameter. It doesn't need to return anything.

app-host-handlers.js

This file is to provide app-host side handling of exec calls (if an exec call is handled on the app-host side, then it doesn't need to be handled on the sim-host side, and in fact any sim-host handler will be ignored). The format is the same as sim-host-handlers.js.

app-host-clobbers.js

This file provides support for "clobbering" built in JavaScript objects. It's form is similar to app-host-handlers.js, expect that the returned object defines what you are clobbering. For example, the built-in support for the geolocation plugin uses this to support simulating geolocation even when the plugin isn't present in the app (just like Ripple does), by returning the following:

{
    navigator: {
        geolocation: {
            getCurrentPosition: function (successCallback, errorCallback, options) {
                // Blah blah blah
            },
            watchPosition: function (successCallback, errorCallback, options) {
                // Blah blah blah
            }
        }
    }
}

The "messages" Object

A messages object is provided to all standard JavaScript files on both the app-host and sim-host side of things. It provides the following methods:

messages.call(method, param1, param2 ...): Calls a method implemented on "the other side" (that were registered by calling messages.register()) and returns a promise for the return value, that is fulfilled when the method returns.

messages.register(method, handler): Registers a method handler, which can be called via messages.call().

messages.emit(message, data): Emits a message with data (scalar value or JavaScript object) which will be received by any code that registers for it (in both app-host and sim-host).

messages.on(message, handler): Register interest in a particular message.

messages.off(message, handler): Un-register interest in a particular message.

Note that:

  • All the above methods are isolated to the plugin - that is, they can only be used to communicate within the plugin's own code. For example, when you emit a message, it will only be received by code for the same plugin that registers to hear it. So different plugins can use the same method and message names without conflict.
  • A method call is always sent from app-host to sim-host or vice versa (that is, a call from app-host can only be handled by a method registered on sim-host, and vice versa).
  • Emitted messages, on the other hand, are sent both "locally" and across to the "other side".

Code of conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

cordova-simulate's People

Contributors

albertinad avatar aleksanderstrochkov avatar andrew-dixon avatar benjaminbi avatar busykai avatar changsi-an avatar cravaterouge avatar dependabot[bot] avatar dlebu avatar dmitrii-snytkin avatar edewit avatar ericcornelson avatar ezioli01 avatar guillaumejenkins avatar itoys avatar jicongw avatar jiglionero avatar johnwargo avatar jwargo avatar kant avatar lexie011 avatar mfish33 avatar mslaguana avatar paymicro avatar redmickey avatar rodberw avatar ruslan-bikkinin avatar sound120 avatar v-mdriml avatar v-zbsail avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cordova-simulate's Issues

Visualization of general simulation status/plugin support status

It would a convenient feature to have a widget (or other UX element) which would reflect the general state of the simulation. For example, general cordova information from the APP_HOST (version, platform_version etc.), list of plugins and their support status, current status of the APP_HOST (connected, ready, disconnected etc.) and similar information.
#21 provides list of plugins, for example, which could be used as the basis for the implementation of such feature.

Enable to keep isolated simulation contexts

Today, the simulation context remains at module level, and some functionality like stopping the simulation and starting a new one cause some issues due to the shared context and asynchronous tasks from previous simulation.

For a full description see #84

[Bug] Geolocation.getPermission is not being handled automatically

While testing this project: https://github.com/ryanjsalva/cordova-simulate-tests/
Using the Geolocation/Locate button with
Windows 10 with Simulate Android
cordova -v 5.4.1
cordova platforms: android 4.1.1, ios 3.9.2

cordova plugins:
cordova-plugin-add-swift-support 1.1.0 "AddSwiftSupport"
cordova-plugin-battery-status 1.1.2 "Battery"
cordova-plugin-camera 2.2.0 "Camera"
cordova-plugin-compat 1.0.0 "Compat"
cordova-plugin-contacts 2.1.0 "Contacts"
cordova-plugin-dbmeter 1.0.3 "DBMeter"
cordova-plugin-device 1.1.2 "Device"
cordova-plugin-device-motion 1.2.1 "Device Motion"
cordova-plugin-device-orientation 1.0.3 "Device Orientation"
cordova-plugin-dialogs 1.2.1 "Notification"
cordova-plugin-file 4.2.0 "File"
cordova-plugin-geolocation 2.2.0 "Geolocation"
cordova-plugin-globalization 1.0.3 "Globalization"
cordova-plugin-inappbrowser 1.4.0 "InAppBrowser"
cordova-plugin-media-capture 1.3.0 "Capture"
cordova-plugin-network-information 1.2.1 "Network Information"
cordova-plugin-splashscreen 3.2.2 "Splashscreen"
cordova-plugin-statusbar 2.1.3 "StatusBar"
cordova-plugin-vibration 2.1.1 "Vibration"
cordova-plugin-whitelist 1.2.2 "Whitelist"
cordova-sqlite-storage 1.4.1 "Cordova sqlite storage plugin"

I get an UNHANDLED EXEC CALL asking for Geolocation.getPermission.:
image

cordova-radio elements don't work in the latest Chrome

After a recent Chrome update (can't pinpoint which), <cordova-radio> elements are no longer mutually exclusive with each other. Clicking a different radio button in the group will select the new one without unselecting the previous one.

It still works fine in other browsers.

XHR proxy can't handle all failures correctly

If an app attempts to make an XHR which fails, we currently don't report the failure back to the client. By failure here I don't mean a 400 or a 500 error, but rather a non-existent domain, or a connection failed or reset. Currently these errors result in cordova-simulate crashing, but if we detect these errors and avoid crashing we still won't be able to report them back to the app in a transparent manner since the call from app_host into cordova-simulate has already successfully connected.

Rearrange third-party folder

Microsoft third-party policy requires each third party IP have its own sub-folder under the third-party folder, with a readme.txt describing the IP (including what version).

Geolocation plugin ignores timeout option

The geolocation simulation ignores the timeout option. For example:

navigator.geolocation.getCurrentPosition(function (pos) {
    ...
}, function (err) {
    ...
}, { timeout: 20000 });

I still get a timeout error after the default 5 sec.

Review usages of constantes in src/modules/constants

The constants modules is inherited from Ripple, and there might be a lot of constants definitions that we are not using, and that we don't need and each plugin can handle their constantes in their context.

SIM_HOST plugin code may send messages ahead of time

In some cases, plugin simulation code on SIM_HOST may send messages ahead of time (before the APP_HOST is able to respond). Currently, there's one specific case: cordova-plugin-device tries to retrieve cordova.version ahead of time. With the merge of #21, it becomes consistently reproducible (in Device widget cordova version information is missing). Since the call never returns, the .fail() handler on such calls is not called either.

Media simulation doesn't follow the plugin specification

The current implementation of media simulation doesn't follow the plugin specification related to:

  • error handling: an instance a MediaError object must be sent when an error happens. That object contains the following properties: code, that seems to be required, and message, that it seems to be optional.
  • the media instance doesn't keep track of the state, so it allows multiple calls to stop and pause APIs. For example, calling stop function when the media is not active (running or paused), it should send an error with the status code MEDIA_ERR_NON_ACTIVE and avoid calling internal stop.

Wrong default device in viewport and device panels

According to the code, the default selected device in the list of both the viewport and device panels should be the "Generic WVGA". However, the first one in the list ("Acer A500") is selected instead.

[confusing ui] I'm not sure what's the Go 16x button is for.

First time I used it I assume it might be the zoom level of the map.
It doesn't seem to be changing that, so now I'm guessing it's something related to the Navigator Simulator (probably the reproduction speed), but it'd be nice if the intent was clearer...

Geolocation: Show the heading value next to the slider

Right now, in the Geolocation panel, the only place the heading value is displayed is in the upper left corner of the map.

We should consider also displaying that value next to the Heading slider (next to the direction letter) to make it easier to set it to the desired value (right now if you want a precise value you have to look at the bottom of the Geolocation panel).

JSON response for missing exec simulation differs between persisting and explicitly specified

When testing the behavior of cordova.exec when there is no pre-defined plugin simulation, I saw this:

>cordova.exec(suc, fai, "fooService", "bar", [1])
undefined
fail
{}
>cordova.exec(suc, fai, "fooService", "bar", [1])
undefined
fail
{"0":""}

The first time it popped up the "Please specify a response" dialog, and I left the field empty and clicked fail, but also told it to persist the result. The first response was just {} as expected, an empty object, but the second time when it used the persisted result the response had a 0 property.

[Suggestion] Double submit of "Choose file"

If you click the "Choose file" button of the camera plugin really fast, it'll sometimes show the open file dialog multiple times in response. This could be an issue particularly in slow machines, if the user doesn't sees a response and clicks again. It'd be nice if the second instance could be automatically be omitted.

cordova-number-entry fields indicate valid values are invalid

Some browsers (Chrome for example) validate the value of a numeric input field based on the value of step. Since this defaults to 1, and we never specify it for cordova-number-entry elements, any non-integer value is flagged as an error. For example, the tooltip for the Latitude field of the Geolocation panel shows something like the following error:

Please enter a valid value. The two nearest valid values are 43 and 44.

Sync viewport and device plugins

Both Viewport and Device panels have a predefined device selection. Changing the predefined device in one panel should update the other panel appropriately.

As part of this change, device metadata should be refactored to be in a shared location so that the 2 plugins (and any other code) can have access to it. It will also make authoring / updating device metadata much easier and straightforward.

We should also use that opportunity to enhance the viewport and device plugins to automatically select a device appropriate for the currently simulated platform (e.g. select iPhone 6 by default if simulating the iOS platform).

Camera: file picker doesn't validate that the result is a valid content

When choosing a file as a response of the exec call of the plugin, or configuring the default image to use as a response, the result of selecting or cancelling picking an image is not validated. When the user cancel, the content is undefined, and an exception is thrown.

Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.

Support host system camera and default camera image

The camera plugin options for using the host system camera and a built-in camera image have been removed, since they were not currently supported.

These functionalities should be implemented and the UI options to select them re-enabled.

Is platform "windows" supported ?

Hi,

I tried to add Windows to the launch.json file:
{
"name": "Simulate Windows in browser",
"type": "cordova",
"request": "launch",
"platform": "windows",
"target": "ie",
"simulatePort": 8000,
"livereload": true,
"cwd": "${workspaceRoot}"
}

but I get always:
[cordova-debug-adapter] Error: Unknown Platform: windows

In my project folder "platforms" exists the sub folder windows and in platforms.json:
{
"windows": "4.4.0",
"android": "4.1.0"
}

Simulation controls panel weird behaviour when collapsing them

When collapsing some control widget panel, the content is not collapsed/hided when its container is collapsed/hided. It does not always happens, it is randomly but easy to reproduce by toggling the panels.

screen shot 2016-04-28 at 3 23 59 pm
screen shot 2016-04-28 at 3 24 19 pm

I've tested on Chrome and Firefox. In Firefox works good but not in Chrome.

The server does a cordova prepare before serving every HTML file

When requested to serve an HTML file, the server will execute a cordova prepare, which adds a noticeable delay when navigating within a simulated app.

Possible solutions are:

  • Only prepare if the served file is the app's start page
  • Only prepare if there have been changes since the last prepare

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.