Coder Social home page Coder Social logo

xebia / xebium Goto Github PK

View Code? Open in Web Editor NEW
75.0 113.0 62.0 2.64 MB

Xebium provides Selenium (webdriver) bindings for FitNesse, with Selenium-IDE support

Home Page: http://xebia.github.com/Xebium/

License: Apache License 2.0

Shell 0.18% JavaScript 13.42% Java 85.51% HTML 0.89%
end-of-life selenium java webdriver fitnesse-fixture

xebium's Introduction

Xebium Build Status

Xebium combines the powers of FitNesse and Selenium. Visit the xebium home page for more details and examples.

Maintainance mode

While Xebium is no longer actively maintained by its original authors, we do strive to respond to issues and PR's as time allows.

A version that depends on newer versions of FitNesse and Selenium is in the works at #148, but (ironically) we feel our testsuite is insufficient to release it without further testing. Help is welcome.

Features

  • Full Selenium-IDE - FitNesse roundtrip with your web tests
  • Create data-driven tests.
  • Tests are executed using the modern WebDriver interfaces and Selenium Server.
  • Tests are run from FitNesse using the SLIM engine.

Getting Started

Execute the following command:

$ mvn -Pfitnesse test

and open a browser, pointing at http://localhost:8000.

Click the Xebium link in order to get to the Xebium section and read on in the Getting Started page.

Have fun!


PS. For those of you who import Xebium as an Eclipse project, run `mvn eclipse:eclipse` to get your classpath setup right.

xebium's People

Contributors

alexanderrosenfeldfmr avatar amolenaar avatar asikkema avatar bartleusink avatar bvklingeren avatar ckreutzer avatar denniebouman avatar iwein avatar kmandr avatar mfriedenhagen avatar mjvdende avatar raboof avatar samitbadle avatar srid99 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

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  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

xebium's Issues

Test table data

I've been testing a lot of tables lately. It would be nice to represent the final table in FitNesse, the same way it's presented on page.

This looks like a nice functionality to test as a plugin. (a plugin framework is required first then)

Pasting a value containing pipes into SeleniumIDE is incorrectly parsed

When a value from a run test, that coincidently contains pipes " | " is pasted into the SeleniumIDE source tab it results in part of the value being removed.
The pipe is occidentally interpreted as a divider (current replacement is based on tabs). When copying the value from IDE to Fitnesse the pipes are escaped, but this is not visible in the run-result from Fitnesse.
The original test script is:

| script |
| start browser | firefox | on url | http://www.bol.com/ |
| ensure | do | open | on | /nl/index.html |
| ensure | do | verifyTitle | on | !-bol.com | bomvol winkels, bomvol voordeel | Welkom-! |
| stop browser |

The pasted source is the following:
script
start browser firefox on url http://www.bol.com/
ensure do open on /nl/index.html
ensure do verifyTitle on bol.com | bomvol winkels, bomvol voordeel | Welkom
stop browser

Typing empty strings is broken with new Selenium dependency

We have tests containing:

|ensure|do|type|on|opmerking|with|hello|
|ensure|do|type|on|opmerking|with||

where with the previous version of Xebium the last statement removes the text "hello" and in the new version (0.4) it does not. I have checked with 2 versions of selenium (2.0rc-1 and 2.0b3) and by using the previous version the check works again.

I'm not really sure what to do with it, but I'm switching back the selenium version dependency in our project.

style="display: none; visibility: hidden;" are not found by xebium where as SeIDE finds them

I have an element with style="display: none; visibility: hidden;" in my page and it is found by Selenium IDE and I tried a test case with TestNg as well and it worked. The same locator(both xpath and css I tried), is not working in Xebium.

ERROR com.xebia.incubator.xebium.SeleniumDriverFixture - Execution of command failed: Element not found

The locators I used are as follows :

  1. css=span[not(contains(@Style,'display:none'))]:contains("Resource type")
  2. css=span:contains("Resource type")
    3)//div/li/ul/li[2]/a/span
    All these 3 worked in SeIDE
    I have tried using waitForElementPresent was getting the following error

Performing | waitForElementPresent | //div/li/ul/li[2]/a/span |
10139 [Thread-1] INFO com.xebia.incubator.xebium.SeleniumDriverFixture - command isElementPresent with value '//div/li/ul/li[2]/a/span' compared to output 'true' is: true
10139 [Thread-1] INFO com.xebia.incubator.xebium.SeleniumDriverFixture - Performing | clickAndWait | //div/li/ul/li[2]/a/span |
10165 [Thread-1] ERROR com.xebia.incubator.xebium.SeleniumDriverFixture - Execution of command failed: Element is not currently visible and so may not be interacted with
System info: os.name: 'Windows 7', os.arch: 'x86', os.version: '6.1', java.version: '1.6.0_25'
Driver info: driver.version: RemoteWebDriver

I am using xebium-0.3-jar-with-dependencies.jar

The function to import a Firefox profile should be able to use a relative path to the profile file

The function to import a Firefox profile file "load custom browser preferences from file" should use a relative path. It now uses the Fitnesse root as a default location.

It would be useful if the path could be set to use the Fitnesse files directory for instance ie "file://files/profile/firefoxprofiel.js"

Furthermore the logging should be extended to show the location of the used .js file.

Tests shouldMatchWithoutRegularExpression and testMultiLineRegexp fail

Failed tests:
testMultiLineRegexp(com.xebia.incubator.xebium.ExtendedSeleniumCommandTest): expected:<[multiple lines]> but was:<[.*multiple lines.*]>

shouldMatchWithoutRegularExpression(com.xebia.incubator.xebium.SeleniumDriverFixtureTest): Expected: is <true> got: <false>

Probably related to the globbing fix in commit 16a53c3

Using storeEval with javascript causes error on Windows

When I use getEval with javastript I do not get the expected output and a unclear error in my logging.

Here's a small example of a random test causing the error (be aware the javascript might be invalid):
| script | selenium driver fixture |
| start browser | firefox | on url | http://www.bol.com/ |
| ensure | do | open | on | /nl/index.html |
| ensure | do | click | on | id=searchfor |
| ensure | do | type | on | id=searchfor | with | Agile Testing |
| ensure | do | clickAndWait | on | id=java_search_button_small |
| ensure | do | clickAndWait | on | link=Agile Testing |
| $descriptiontext= | is | getText | on | css=div.product_description > p |
| $filteredoutput= | is | getEval | on | regexp:/widespread.*.exec('$descriptiontext')[1] |
| stop browser |

The logfile states the following error:
21734 [Thread-3] INFO com.xebia.incubator.xebium.SeleniumDriverFixture - Storing result from | getEval | regexp:/widespread.*.exec('Testing is a key component of agile development. The widespread adoption of agile methods has brought the need for effective testing into the limelight, and agile projects have transformed the role of testers. Much of a tester's function, however, remains largely misunderstood. What is the true role of a tester? Do agile teams actually need members with QA backgrounds? What does it really mean to be an "agile tester?"')[1] |
21796 [Thread-3] ERROR com.xebia.incubator.xebium.SeleniumDriverFixture - Execution of command failed: null (WARNING: The server did not provide any stacktrace information); duration or timeout: 16 milliseconds
Build info: version: '2.7.0', revision: '13926', time: '2011-09-23 15:09:51'
System info: os.name: 'Windows XP', os.arch: 'x86', os.version: '5.1 build 2600 Service Pack 3', java.version: '1.6.0'
Driver info: driver.version: RemoteWebDriver
23265 [Thread-3] INFO com.xebia.incubator.xebium.SeleniumDriverFixture - Command processor stopped

waitFor commands do not work in combination with "check" method

The current behavior of the Xebium formatter is that waitFor commands are formatted with the check method, in stead of the ensure method, the result is that the wait is not executed.

It would be nice if it could actually functional as a check, but it needs to wait for a timeout rather than returning immediately (which it does not).

Select problem on /div popup screen

For certain combinations of OS/Firefox versions a specific type of /div is not recognised, causing verifications and buttons clicks not to be executed.

Xebium version 0.3
For Windows XP with Firefox 3.6.xx this particular type of popup is not found
Upgrading to Firefox 4.x solves the problem

Xebium version 0.4
For Windows XP with Firefox 4.x this particular type of popup is (again) not found
Problem most probable is caused by Selenium2.0rc2 (as opposed to the Selenium2.0b2 which is used by Xebium 0.3)

Testscript to reproduce this problem (does work under SeleniumIDE all version combinations):

| script | selenium driver fixture |
| start browser | firefox | on url | http://www.rabobank.nl |
| set step delay to | 500 |
| ensure | do | open | on | /particulieren/producten/verzekeren/zorgverzekering_module/ |
| ensure | do | type | on | premiumCalculationPersons[0].birthDate | with | 01-11-1980 |
| ensure | do | click | on | premiumCalculationPersons[0].excess |
| ensure | do | select | on | premiumCalculationPersons[0].excess | with | label=€ 170 + € 0 |
| ensure | do | verifyChecked | on | collectivityType0 |
| ensure | do | click | on | collectivityType3 |
| ensure | do | waitForElementPresent | on | dialog_select_collectivity_submitbutton |
| ensure | do | verifyText | on | css=h3 | with | Collectiviteitskorting |
| ensure | do | click | on | dialog_select_collectivity_submitbutton |
| ensure | do | verifyTitle | on | !-Rabobank - Zorgverzekering ZorgActief-! |
| ensure | do | click | on | 1 |
| ensure | do | verifyTextPresent | on | Collectiviteitskorting voor studenten |
| ensure | do | click | on | submit_option_chosen_in_student_warning_commit |
| ensure | do | verifyTextNotPresent | on | Collectiviteitskorting voor studenten |
| stop browser |

storeCssCount not supported

EXCEPTION:java.lang.UnsupportedOperationException: storeCssCount
at org.openqa.selenium.WebDriverCommandProcessor.execute(WebDriverCommandProcessor.java:141)
at org.openqa.selenium.WebDriverCommandProcessor.doCommand(WebDriverCommandProcessor.java:74)
at com.xebia.incubator.xebium.SeleniumDriverFixture.executeCommand(SeleniumDriverFixture.java:463)
at com.xebia.incubator.xebium.SeleniumDriverFixture.executeCommand(SeleniumDriverFixture.java:438)
at com.xebia.incubator.xebium.SeleniumDriverFixture.isOn(SeleniumDriverFixture.java:337)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at fitnesse.slim.MethodExecutor.callMethod(MethodExecutor.java:43)
at fitnesse.slim.MethodExecutor.invokeMethod(MethodExecutor.java:30)
at fitnesse.slim.MethodExecutor.findAndInvoke(MethodExecutor.java:53)
at fitnesse.slim.FixtureMethodExecutor.execute(FixtureMethodExecutor.java:18)
at fitnesse.slim.StatementExecutor.getMethodExecutionResult(StatementExecutor.java:189)
at fitnesse.slim.StatementExecutor.callAndAssign(StatementExecutor.java:201)
at fitnesse.slim.Statement.callAndAssign(Statement.java:117)
at fitnesse.slim.Statement.execute(Statement.java:79)
at fitnesse.slim.ListExecutor.execute(ListExecutor.java:36)
at fitnesse.slim.SlimServer.executeInstructions(SlimServer.java:81)
at fitnesse.slim.SlimServer.processTheInstructions(SlimServer.java:73)
at fitnesse.slim.SlimServer.processOneSetOfInstructions(SlimServer.java:57)
at fitnesse.slim.SlimServer.tryProcessInstructions(SlimServer.java:43)
at fitnesse.slim.SlimServer.serve(SlimServer.java:30)
at fitnesse.socketservice.SocketService$ServerRunner.run(SocketService.java:95)
at java.lang.Thread.run(Thread.java:722)

As a workaround storeXpathCount can be used

contextMenuAndWait not working

It seems the 'contextMenuAndWait' is not working with xebium.
Any reason what's wrong/why I get the error below?

Error:
do The instance scriptTableActor. does not exist

Code:

!today (YYYY-MM-dd HH.mm.ss)

| script|
|save screenshot after | every step| in folder | C:\Xebium\SuiteDvlp.CommonTests.CoordinatieSuite.OverzichtDossiersContextMenuText!today (YYYY-MM-dd HH.mm.ss)|
|do |open|on |/Coordinatie/OverzichtDossiers|
|do|contextMenuAndWait | requestTEST-0001 | |

Set test execution speed

We figured that in some cases the tests are executed just to fast. Provide a means to set a delay between commands, just like the SeIDE speed slider.

PS. May also be nice when doing presentations ;)

Receiving Apache Velocity initiation stack trace while attempting to install most up-to-date version of Xebium

Attempting to install the most up-to-date version of Xebium and set it up in Eclipse, I received the following error while issuing the command "mvn -Pfitnesse test":

org.apache.velocity.exception.VelocityException: Failed to initialize an instance of org.apache.velocity.runtime.log.ServletLogChute with the current runtime configuration.

After doing some digging, the issue was discovered to be related to Apache Velocity 1.5. The most recent version is 1.7 and resolves the issue. The fitnesse-111025.jar used contains an older version of Apache Velocity that has a bad logger and since the build is integrated as a maven dependency, I had to implement some creative fixes. I had to actually download the Apache Velocity 1.7 jar file, unjar the dependency jar file and Velocity 1.7, replace the contents of the fitnesse-111025.jar file with the updated version 1.7, and then jar fitnesse-111025.jar. I renamed the file to fitnesse-111026.jar. Then I created a dummy directory in my .m2 repo simulating the fitnesse-111025.jar. I updated the fitnesse.version in the POM dependency to fitnesse-111026 so my maven project was pointed at the updated Jar file. This took me a while to figure out, but I thought it should be brought to your attention that the latest build on the site is faulty. The workaround is exhaustive and confusing for new xebium users.

Xebium formatter conversion problems

When opening Selenium scripts in Selenium IDE that contain non Xebium content, while the Xebium formatter is selected, its content is removed and replaced with the default empty Xebium script, which contains the following lines:
| script | selenium driver fixture |
| start browser | firefox | on url | http:/// |
| stop browser |

Whenever a script is opened with wrong (non Xebium) content it should either convert it or provide an appropriate error, if it fails at this it should non mutate the original content.

Update Fitnesse

We're depending on an older version of Fitnesse. Let's update!

verify command uses glob by default

Currently verify commands use a glob pattern which is not in all cases wanted.

A verifyTextPresent should use a glob pattern by default, since it does not verify a specific location
A verifyText does use a locater and should be specific in the assertion and not use a glob by default.

Here's a simple test to demonstrate the behaviour:

| script | selenium driver fixture |
| start browser | firefox | on url | http://localhost:8000 |
| ensure | do | open | on | / |
| ensure | do | verifyText | on | css=span.page_title | with | !-FrontPage-! |
| ensure | do | verifyNotText | on | css=span.page_title | with | Page |
| ensure | do | verifyText | on | css=span.page_title | with | glob:*Page |
| ensure | do | verifyTextPresent | on | Page |
| stop browser |

I've seen similar behaviour with the verifyCookie command, probably other commands need to be adjusted as well, the current approach (using glob by default) is too generic.

When the base-url from a pasted buffer is not the same as the url in SeleniumIDE it overwritten

When the base-url from a pasted buffer is not the same as the base-url in the SeleniumIDE address bar, the base-url from the source is ignorer and replaced by SeleniumIDE's base-url.

Reproduce:

  1. SeleniumIDE has google.com in the (base-url) address bar
  2. Copy a testscript from Fitnesse with amazone.com for base-url
  3. Paste the buffer in the source tab of SeleniumIDE
  4. When running the script it fails because the SeleniumIDE base-url overrules the url from the script
  5. When checking the source the original url has been replaced by the SeleniumIDE one.

FitNesse should show the returned values (expected/actual) if returned by Selenium

If a Selenium command fails during execution Fitnesse currently only shows a failure, by means of a red line, the actual value returned by Selenium is only available in the logfile (Output Captured).

It would be much more efficient if the returned values would appear in the fixture, by means of an expected [] and an actual [] value.

verifySelectOptions/getSelectOptions function is not working

When trying to retrieve the select options from a dropdown using verifySelectOptions (getSelectOptions) an error occurs, an incorrect value is retrieved:

INFO com.xebia.incubator.xebium.SeleniumDriverFixture - Command 'getSelectOptions' returned '[Ljava.lang.String;@bf1d3b' => not ok, expected 'Alle artikelen,Nederlandse boeken,Engelse boeken,etc.'

This simple test reproduces the problem, the value stored in the variable makes the problem explicit.

| script | selenium driver fixture |
| start browser | firefox | on url | http://www.bol.com |
| ensure | do | open | on | /nl/index.html |
| $blabla= | is | getSelectOptions | on | product_select |
| ensure | do | verifySelectOptions | on | product_select | with | Alle artikelen,Nederlandse boeken,Engelse boeken,Alle boeken,Muziek,Dvd,Speelgoed,Games,Elektronica,Computer |
| stop browser |

Store, StoreEval selenium methods for storing variables and using variable substitution doesn't work

Not implemented yet. We'd like to be able to execute something like:

| THREAD | is | storeText | on | //html/body/pre |
| THREADID | is | storeEval | on | "!-${THREAD}-!".match("'([0-9]*)'")[1] |
| ensure | do | open | on | /monitor/thread/!-${THREADID}-!.txt |
| ensure | do | verifyTextPresent | on | Stackelements |

where THREAD and THREADID are selenium variables. Unfortunately fitNesse and selenium both use the ${VAR} syntax for varables, so we'll probably need to escape this in fitnesse.

Support all waitFor- commands

Support all waitFor- command by polling for the condition to become true.

Currently the driver only supports "waitForCondition", "waitForFrameToLoad", "waitForPageToLoad" and "waitForPopUp". The rest should also be supported (as verify commands)

Parent pom for Xebium projects

Copying parts of the xebium pom.xml in order to get a new fitnesse project started (e.g. ant plugin for starting fitnesse, including maven-classpath-plugin and all that) is not ideal.

Proposal is to split the current Xebium project:

  1. xebium-project-parent
  2. xebium-fixture (the fitnesse fixture)
  3. xebium-ide-plugin (the SeIDE plugin)
  4. xebium-project-template (something to get you up and running in no time)

Maybe the xebium-project-template should become a maven archetype as well?

xebium running from command line 2

Is it possible to run xebium test from command line
i.e providing a particular test page.
If we want to use FitNesse.UserGuide.CommandLineTestRunner. options:
we have to write that in pom.xml but I want to do this task on starting of xebium i.e with the command
mvn -Pfitnesse test < my test page for test>

I am not having rights to open the issue

MavenClasspathExtractionException when saucelab propertie file is missing

When no saucelabs.properties file is available the maven classpath generation causes an exception:

fitnesse.wikitext.widgets.MavenClasspathExtractionException: org.apache.maven.project.ProjectBuildingException: 12 problems were encountered while building the effective model for com.xebia.incubator:xebium:0.6-SNAPSHOT
[ERROR] Resolving expression: '${sauce.user}': Detected the following recursive expression cycle in 'sauce.user': [sauce.user] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.user}': Detected the following recursive expression cycle in 'sauce.user': [sauce.user] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.user}': Detected the following recursive expression cycle in 'sauce.user': [sauce.user] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.user}': Detected the following recursive expression cycle in 'sauce.user': [sauce.user] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
[ERROR] Resolving expression: '${sauce.accesskey}': Detected the following recursive expression cycle in 'sauce.accesskey': [sauce.accesskey] @
for project com.xebia.incubator:xebium:0.6-SNAPSHOT at /Users/cirilowortel/Documents/xebia/Xebium/master/pom.xml
fitnesse.wikitext.widgets.MavenClasspathExtractor.extractClasspathEntries(MavenClasspathExtractor.java:50)
fitnesse.wikitext.widgets.MavenClasspathSymbolType.getClasspathElements(MavenClasspathSymbolType.java:51)
fitnesse.wikitext.widgets.MavenClasspathSymbolType.toTarget(MavenClasspathSymbolType.java:30)
fitnesse.wikitext.parser.Translator.translate(Translator.java:24)
fitnesse.wikitext.parser.Translator.translate(Translator.java:29)
fitnesse.wikitext.parser.Collapsible.toTarget(Collapsible.java:52)
fitnesse.wikitext.parser.Translator.translate(Translator.java:24)
fitnesse.wikitext.parser.Translator.translateTree(Translator.java:17)
fitnesse.wiki.PageData.translateToHtml(PageData.java:243)
fitnesse.wiki.PageData.getHtml(PageData.java:198)
fitnesse.html.HtmlUtil.makePageHtmlWithHeaderAndFooter(HtmlUtil.java:241)
fitnesse.responders.WikiPageResponder.generateHtml(WikiPageResponder.java:101)
fitnesse.responders.WikiPageResponder.makeHtml(WikiPageResponder.java:89)
fitnesse.responders.WikiPageResponder.makePageResponse(WikiPageResponder.java:71)
fitnesse.responders.WikiPageResponder.makeResponse(WikiPageResponder.java:46)
fitnesse.FitNesseExpediter.createGoodResponse(FitNesseExpediter.java:123)
fitnesse.FitNesseExpediter.makeResponse(FitNesseExpediter.java:106)
fitnesse.FitNesseExpediter.start(FitNesseExpediter.java:48)
fitnesse.FitNesseServer.serve(FitNesseServer.java:24)
fitnesse.FitNesseServer.serve(FitNesseServer.java:17)
fitnesse.socketservice.SocketService$ServerRunner.run(SocketService.java:95)
java.lang.Thread.run(Thread.java:680)

Unable to run basic test with HTMLUnit driver

I'm trying to run a basic test with the HTMLUnit Selenium driver, but it fails when starting the 'browser'.
I'm using this script:

| script | selenium driver fixture |
| start browser | htmlunit | on url | http://xebia.github.com/ |
| ensure | do | open | on | /Xebium/ |
| ensure | do | clickAndWait | on | link=Xebia App incubator |
| stop browser |

And i'm getting this exception:

EXCEPTION:com.thoughtworks.selenium.SeleniumException: Unable to determine which driver to use: Capabilities [{platform=ANY, browserName=htmlunit, version=}]
at org.openqa.selenium.SuppliesWebDriver.get(SuppliesWebDriver.java:45)
at org.openqa.selenium.SuppliesWebDriver.get(SuppliesWebDriver.java:28)
at org.openqa.selenium.WebDriverCommandProcessor.start(WebDriverCommandProcessor.java:236)
at org.openqa.selenium.WebDriverCommandProcessor.start(WebDriverCommandProcessor.java:224)
at com.xebia.incubator.xebium.SeleniumDriverFixture.startBrowserOnUrl(SeleniumDriverFixture.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at fitnesse.slim.MethodExecutor.callMethod(MethodExecutor.java:47)
at fitnesse.slim.MethodExecutor.invokeMethod(MethodExecutor.java:31)
at fitnesse.slim.MethodExecutor.findAndInvoke(MethodExecutor.java:87)
at fitnesse.slim.FixtureMethodExecutor.execute(FixtureMethodExecutor.java:18)
at fitnesse.slim.StatementExecutor.call(StatementExecutor.java:155)
at fitnesse.slim.Statement.callMethodAtIndex(Statement.java:99)
at fitnesse.slim.Statement.call(Statement.java:92)
at fitnesse.slim.Statement.execute(Statement.java:72)
at fitnesse.slim.ListExecutor.execute(ListExecutor.java:36)
at fitnesse.slim.SlimServer.executeInstructions(SlimServer.java:93)
at fitnesse.slim.SlimServer.processTheInstructions(SlimServer.java:78)
at fitnesse.slim.SlimServer.processOneSetOfInstructions(SlimServer.java:69)
at fitnesse.slim.SlimServer.tryProcessInstructions(SlimServer.java:55)
at fitnesse.slim.SlimServer.serve(SlimServer.java:30)
at fitnesse.socketservice.SocketService$ServerRunner.run(SocketService.java:95)
at java.lang.Thread.run(Thread.java:619)

UnsupportedOperationException since latest changes

Hi there,

since the latest updates (the moving of webdriver instance creation to seperate class) i get only UnsupportedOperationException when trying to run some tests:

EXCEPTION:java.lang.UnsupportedOperationException: setTimeout
at org.openqa.selenium.WebDriverCommandProcessor.execute(WebDriverCommandProcessor.java:141)
at org.openqa.selenium.WebDriverCommandProcessor.doCommand(WebDriverCommandProcessor.java:74)
at com.xebia.incubator.xebium.SeleniumDriverFixture.executeCommand(SeleniumDriverFixture.java:466)
at com.xebia.incubator.xebium.SeleniumDriverFixture.setTimeoutOnSelenium(SeleniumDriverFixture.java:193)
at com.xebia.incubator.xebium.SeleniumDriverFixture.startBrowserOnUrl(SeleniumDriverFixture.java:122)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at fitnesse.slim.MethodExecutor.callMethod(MethodExecutor.java:43)
at fitnesse.slim.MethodExecutor.invokeMethod(MethodExecutor.java:30)
at fitnesse.slim.MethodExecutor.findAndInvoke(MethodExecutor.java:53)
at fitnesse.slim.FixtureMethodExecutor.execute(FixtureMethodExecutor.java:18)
at fitnesse.slim.StatementExecutor.getMethodExecutionResult(StatementExecutor.java:189)
at fitnesse.slim.StatementExecutor.call(StatementExecutor.java:179)
at fitnesse.slim.Statement.callMethodAtIndex(Statement.java:104)
at fitnesse.slim.Statement.call(Statement.java:97)
at fitnesse.slim.Statement.execute(Statement.java:77)
at fitnesse.slim.ListExecutor.execute(ListExecutor.java:36)
at fitnesse.slim.SlimServer.executeInstructions(SlimServer.java:81)
at fitnesse.slim.SlimServer.processTheInstructions(SlimServer.java:73)
at fitnesse.slim.SlimServer.processOneSetOfInstructions(SlimServer.java:57)
at fitnesse.slim.SlimServer.tryProcessInstructions(SlimServer.java:43)
at fitnesse.slim.SlimServer.serve(SlimServer.java:30)
at fitnesse.socketservice.SocketService$ServerRunner.run(SocketService.java:95)
at java.lang.Thread.run(Thread.java:722)

alias names for locators are not recognized when part of a longer name

Using the alias fixture causes problems when the alias is only part of a longer locator name (which in some cases is required).

When an alias is part of a locator it should be recognized too, or Fitnesse arguments should be interpreted when contained in an alias.

Example:
This is an example of an xpath expression matching a specific cell in a table (the table does not have fixed identification)
//td[@Class="TitleCell" and contains(text(),'Besluitvorming')]/following::td[contains(@id,'e_saw') and contains(@id,'1_1_2')]

The last two numbers match to an actual cell in the table.

If this is to be uses in a FitNesse scenario the numbers would be replaced with variables, so my test would contain:
| script |
| check | is | veriftyText | on | //td[@Class="TitleCell" and contains(text(),'Besluitvorming')]/following::td[contains(@id,'e_saw') and contains(@id,'1_@columnnumber_@rownumber')] | specificvalue |

Since this locator is unreadable, I would use an alias for it
| script |
| add alias | tablecell | for locator | //td[@Class="TitleCell" and contains(text(),'Besluitvorming')]/following::td[contains(@id,'e_saw') and contains(@id,'1_@columnnumber_@rownumber')] |

My test would look like:
| script |
| check | is | veriftyText | on | %tablecell_1_2')] | specificvalue |
(Notice the closing characters ')] behind the locator name, which are part of the original xpath)

In this format the alias is not recognized as an existing value, apparently a exact match is expected.

If I put the entire locator (including the FitNesse argument names in the alias, the arguments are not substituted.

Xebium-Selenium formatter does not convert variables correctly

When a script is recorded that uses variables the conversion is not always correct. In the exacmple script below in the last "waitForText" it uses both ${myVariable} as well as $myVariable. The translation should not use accolades, FitNesse interprets those as FitNesse variables and will give a "variable not defined error":

| script |
| start browser | firefox | on url | http://www.google.nl/ |
| ensure | do | open | on | / |
| ensure | do | type | on | id=lst-ib | with | xebium |
| ensure | do | click | on | name=btnG |
| $myVariable= | is | storeText | on | css=em |
| ensure | do | clickAndWait | on | link=Xebium - Selenium from FitNesse |
| ensure | do | echo | on | $myVariable |
| ensure | do | open | on | / |
| ensure | do | type | on | id=lst-ib | with | $myVariable |
| ensure | do | click | on | name=btnG |
| ensure | do | waitForText | on | link=${myVariable} | with | $myVariable |
| stop browser |

Technical errors do not result in a failing test

When running tests from Fitnesse when objects are not found an error is thrown in the log file, this does however not cause a test to fail, the executed command returns green and no script error is shown.

In this case in the output captured by FitNesse an ERROR is thrown.
16562 [Thread-3] ERROR com.xebia.incubator.xebium.SeleniumDriverFixture - Execution of command failed: Element not found in the cache; duration or timeout: 31 milliseconds
Build info: version: '2.7.0', revision: '13926', time: '2011-09-23 15:09:51'
System info: os.name: 'Windows XP', os.arch: 'x86', os.version: '5.1 build 2600 Service Pack 3', java.version: '1.6.0'
Driver info: driver.version: RemoteWebDriver

This should in some way result in an error in Fitnesse

Xebium should be LGPL licensed

Xebium should be covered by some licensing model in order for larger companies to use it without having to fear unexpected lawsuits or licence fees.

LGPL seems a qualified licensing model

bar ('|') needs escaping

Stewart Says:
Posted at: February 8, 2012 at 1:49 pm (Edit)
Hi There,

A point to out for is that if you have a ‘|’ in some text, such as in the page title, this needs to be converted to wiki syntax ‘!-|-!’ in order for FitNesse not to interpret it as a table column separator.
It would be a really nice touch if the Xebium formatter plugin for Selenium IDE did this automatically.
See this URL for more info: http://old.nabble.com/escape-|-%28vertical-bar%29-in-fitnesse-wiki-td22298159.html

Thanks!

Cross Browser Support Glitches

Though xebium is working fine with firefox 3.6.x
but its very very slow in IE
and is not able to run tests in chrome and safari.

Please update to support all basic browsers

a "git clone" + "mvn -Pfitnesse test" give me a compilation error

Hi,

I try Xebium and after a git clone and a mvn -Pfitnesse test I get a compilation error.

The project can't find any org.openqa.selenium.server.* classes.

[Xebium (master u=)]$ mvn -Pfitnesse test
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Xebium 0.9-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ xebium ---
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ xebium ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ xebium ---
[INFO] Compiling 10 source files to /Users/cyrillakech/Wikeo/workspace/Xebium/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] error: error reading /Users/cyrillakech/.m2/repository/org/seleniumhq/selenium/selenium-server/2.23.1/selenium-server-2.23.1.jar; cannot read zip file
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[28,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[29,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[30,44] package org.openqa.selenium.server.htmlrunner does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[45,9] cannot find symbol
symbol : class SeleniumServer
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[24,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[25,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[26,37] package org.openqa.selenium.server.cli does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[36,16] cannot find symbol
symbol : class SeleniumServer
location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[60,2] cannot find symbol
symbol : class RemoteControlConfiguration
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[60,49] cannot find symbol
symbol : class RemoteControlConfiguration
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[64,22] cannot find symbol
symbol : class SeleniumServer
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[97,3] cannot find symbol
symbol : class HTMLLauncher
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[97,31] cannot find symbol
symbol : class HTMLLauncher
location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[56,15] cannot find symbol
symbol : class RemoteControlConfiguration
location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[63,25] cannot find symbol
symbol : variable RemoteControlLauncher
location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[67,29] cannot find symbol
symbol : class SeleniumServer
location: class com.xebia.incubator.xebium.SeleniumServerFixture
[INFO] 17 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.840s
[INFO] Finished at: Tue Jun 19 17:16:12 CEST 2012
[INFO] Final Memory: 12M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project xebium: Compilation failure: Compilation failure:
[ERROR] error: error reading /Users/cyrillakech/.m2/repository/org/seleniumhq/selenium/selenium-server/2.23.1/selenium-server-2.23.1.jar; cannot read zip file
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[28,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[29,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[30,44] package org.openqa.selenium.server.htmlrunner does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[45,9] cannot find symbol
[ERROR] symbol : class SeleniumServer
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[24,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[25,33] package org.openqa.selenium.server does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[26,37] package org.openqa.selenium.server.cli does not exist
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[36,16] cannot find symbol
[ERROR] symbol : class SeleniumServer
[ERROR] location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[60,2] cannot find symbol
[ERROR] symbol : class RemoteControlConfiguration
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[60,49] cannot find symbol
[ERROR] symbol : class RemoteControlConfiguration
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[64,22] cannot find symbol
[ERROR] symbol : class SeleniumServer
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[97,3] cannot find symbol
[ERROR] symbol : class HTMLLauncher
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleneseScriptFixture.java:[97,31] cannot find symbol
[ERROR] symbol : class HTMLLauncher
[ERROR] location: class com.xebia.incubator.xebium.SeleneseScriptFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[56,15] cannot find symbol
[ERROR] symbol : class RemoteControlConfiguration
[ERROR] location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[63,25] cannot find symbol
[ERROR] symbol : variable RemoteControlLauncher
[ERROR] location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] /Users/cyrillakech/Wikeo/workspace/Xebium/src/main/java/com/xebia/incubator/xebium/SeleniumServerFixture.java:[67,29] cannot find symbol
[ERROR] symbol : class SeleniumServer
[ERROR] location: class com.xebia.incubator.xebium.SeleniumServerFixture
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Paste tests directly from FitNesse pages in Selenium IDE

When a test has been executed I want to copy the performed test directly into the Selenium IDE. This makes it easy to test when scenario tables are used, for example.

Basically this means replacing tabs with pipes (|) and adding a pipe in front of the line.

Special care should be taken in case of variable substitutions:

$varName->[someText]
$varName<-[someText]

Log4j config in xebium jar

Please remove the log4j.properties from the src/main/resources directory for it is packaged with the final jar. This pollutes the logs of software using Xebium.

Xebium setup in Eclipse requires user to update package names

All of the packages listed in the src directory have the prefix "main.java". I had to manually rename each package and update each individual *.java file to compile the project correctly. This process should be explained in your setup instructions or should be dealt with in the current release.

Be more flexible with selecting a way to execute tests

I've been running some tests with Sauce Labs today. It strikes me as annoying that I have to change my start-browser command every time I want to test on another environment.

The dependency on browser can be dealt with by defining it as a variable. However I can test to:

  1. local, using web driver
    | start browser | firefox | on url | http://example.saucelabs.com |
  2. local, using selenium server (requires server to be started using SeleniumServerFixture
    | start browser | firefox | on url | http://example.saucelabs.com | using remote server |
  3. Remotely, using web driver (e.g. to SauceLabs) (Se2 style)
    | Need to come up with something, key-value pairs have to be defined in a Capabilities object and passed to a RemoteWebDriver instance |
  4. Remotely, using Selenium server (Se1 style)
    | start browser | { "username": "your name", "access-key": "some-uuid", "os": "Windows 2003", "browser": "firefox", "browser-version": "7", "name": "Testing Selenium 1 from Xebium" } | on url | http://example.saucelabs.com | using remote server on host | ondemand.saucelabs.com | on port | 80 |

For each version different statements are included. This makes it very complex to switch from one config to another (in a CI setting it's not possible even).

One solution would be to use the syntax as shown in option 4. and allow that to be used for option 1 as well (they're different code paths now!). The org.json.json package is already included through Selenium-server, so we already have that dependency. Defining a special words remote-server with a format server:port' will make the| using remote server |part obsolete. Makingremote-serveran empty string would default tolocalhost:4444`.

TODO: How to distinguish between WebDriver and Http (Selenium 1) driver?
How can this be easily configured in a CI setting? Do we want a property file/system property to set this?

When a buffer is pasted into the SeleniumIDE source tab and the test is directly run, the source is reverted

When a buffer is pasted into the SeleniumIDE source tab and a test is directly run, the source is reverted to whatever was there before.

Reproduce:

  1. Open SeleniumIDE with a test available
  2. Copy a testscript from Fitnesse
  3. Paste it into the source tab of SeleniumIDE, replacing the available script.
  4. Press the "Play current testcase" button.
    The test is reverted to the previous test, the paste script has not been parsed yet.

The ...NotPresent commands do not work

The commands VerifyElementNotPresent, VerifyAlertNotPresent etcetra do not work in FitNesse.
When running commands in Selenium itself (without use of FitNesse) on same test object commands do work.

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.