diff --git a/.hgignore b/.hgignore index a94f07441a74ff82490ed910c83d38a3a8b8b94e..c231bf514e0d8abe11a8eb4f0f0af5bea3943314 100644 --- a/.hgignore +++ b/.hgignore @@ -11,6 +11,7 @@ syntax: glob # mvn build trees target/* +cargo/* # deprecated scripting files *.pl diff --git a/pom.xml b/pom.xml index 1eda265036da1fd47cfd6c1466e7538356e5e384..67481dd6ffdff03d5951545be19bc007cfeeb933 100644 --- a/pom.xml +++ b/pom.xml @@ -172,7 +172,65 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <org.springframework.version>3.0.5.RELEASE</org.springframework.version> - <skipTests>true</skipTests> + + <!-- properties for testing and Q&A --> + <!-- by default no tests are executed so far (April 2011). Use appropriate profiles and properties on the command line --> + <skipTests>true</skipTests> + <skipITs>true</skipITs> + <!-- properties to define the testing environment + values: hsql / mysql --> + <test.env>hsql</test.env> + <!-- olat.local.properties to distinguish multiple single and cluster olat instances on a single machine--> + <test.env.db.name>olattest</test.env.db.name> + <test.env.db.user>olat</test.env.db.user> + <test.env.db.pass>olat</test.env.db.pass> + <test.env.db.host.port>3306</test.env.db.host.port> + <test.env.db.hibernate.ddl.auto>create</test.env.db.hibernate.ddl.auto> + <test.env.instance.id>myolat</test.env.instance.id> + <test.env.jms.broker.port>61616</test.env.jms.broker.port> + <test.env.jmx.rmi.port.0>3000</test.env.jmx.rmi.port.0> + <test.env.jmx.rmi.port.1>3001</test.env.jmx.rmi.port.1> + <test.env.jmx.rmi.port.2>3002</test.env.jmx.rmi.port.2> + + <!-- this version is defined by the dependency <groupId>org.olat.testutils</groupId> <artifactId>zipped-tomcat6x</artifactId> and the herein zipped tomcat installation --> + <container.tomcat.version>6.0.32</container.tomcat.version> + <!-- install dir is important for the -Pinstall-tomcats profile. + These few lines define the default tomcat installation variables for installation and running a local tomcat cluster. + If you want to reuse an existing tomcat installation, set the container.tomcat.*.home instead. --> + <container.tomcat.one.install.dir>${basedir}/cargo/tomcat/one/</container.tomcat.one.install.dir> + <container.tomcat.one.home>${container.tomcat.one.install.dir}/apache-tomcat-${container.tomcat.version}</container.tomcat.one.home> + <!-- The port.part is used in several places to create cluster which follows the template: + servlet port 8181 + administration ports 8109, 8105 + go to the src/test/profile/cluster/tomcat*/conf and lib/ to see the actual replacements.--> + <container.tomcat.one.port.part>81</container.tomcat.one.port.part> + <container.tomcat.one.port>${container.tomcat.one.port.part}${container.tomcat.one.port.part}</container.tomcat.one.port> + <container.tomcat.two.install.dir>${basedir}/cargo/tomcat/two/</container.tomcat.two.install.dir> + <container.tomcat.two.home>${container.tomcat.two.install.dir}/apache-tomcat-${container.tomcat.version}</container.tomcat.two.home> + <container.tomcat.two.port.part>82</container.tomcat.two.port.part> + <container.tomcat.two.port>${container.tomcat.two.port.part}${container.tomcat.two.port.part}</container.tomcat.two.port> + + <!-- the selenium client version which is also by the maven-selenium-plugin, + using the latest selenium a.k.a selenium 2.0 needs a migration of the tests and maven setup. --> + <selenium-client.version>1.0.2</selenium-client.version> + <!-- the selenium configuration needed to configure the tomcats, selenium context and maven failsafe (testng) runner. + The tomcat knows which user to add just for selenium testcases, see additionalUserContext.xml + The selenium context is defined in the defaultcontext.xml and has variable replacements as specified above. + The failsafe plugin uses the testng.xml file which comes from this folder. + In order to customize the selenium tests execution follow the steps: + 1) copy the test/profile/selenium/config folder to a save place + 2) edit the contents of the files (i.e. change executed seleniumtests, add firefox browser executable path to defaultcontext.xml etc.) + 3) run maven among other parameters with -Dselenium.config.files.path="<your-path-without-special-chars>" --> + <selenium.config.files.path>src/test/profile/selenium/config</selenium.config.files.path> + <!-- proposal for setting the firefox executable path, which could be used as variable in the defaultcontext.xml + important if using a firefox script which does not allow to kill the firefoxes after usage. (e.g. Suse 64Bit)--> + <selenium.config.firefox.path>unused/by/default</selenium.config.firefox.path> + + <!-- properties for debugging --> + <!-- for debugging reason it may be helpful to set this with + -Dcargo.container.wait=true to see if the container is up and running for the seleniumtests. --> + <cargo.container.wait>false</cargo.container.wait> + <cargo.container.timeout>300000</cargo.container.timeout> </properties> <profiles> <profile> @@ -217,6 +275,830 @@ </build> </profile> + + <profile> + <id>hsqlunittests</id> + <activation> + <property> + <name>with-hsql</name> + </property> + </activation> + <properties> + <skipTests>false</skipTests> + <skipITs>true</skipITs> + <testFailureIgnore>false</testFailureIgnore> + <test.env.db.hibernate.ddl.auto>create</test.env.db.hibernate.ddl.auto> + <test.env>hsql</test.env> + </properties> + <build> + <plugins> + <plugin> + <!-- Documentation: http://maven.apache.org/plugins/maven-surefire-plugin/ --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.8.1</version> + <configuration> + <argLine>-Xmx1024m -Xms1024m</argLine> + <systemPropertyVariables> + <java.io.tmpdir>${project.build.directory}/olatdata</java.io.tmpdir> + </systemPropertyVariables> + <testNGArtifactName>none:none</testNGArtifactName> + <includes> + <include>**/AllTestsOlatCoreJunit4.java</include> + <include>**/AllTestsJunit4.java</include> + </includes> + </configuration> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <id>copy-resources-4-unittests</id> + <!-- hook in to copy maven.build.properties to allow test and integration-test phase run properly --> + <phase>generate-test-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${basedir}/target/test-classes</outputDirectory> + <resources> + <resource> + <!-- place resources you like to get filtered an copied --> + <directory>src/test/profile/${test.env}</directory> + <includes> + <include>olat.local.properties</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <profile> + <id>mysqlunittests</id> + <activation> + <property> + <name>with-mysql</name> + </property> + </activation> + <properties> + <skipTests>false</skipTests> + <skipITs>true</skipITs> + <testFailureIgnore>false</testFailureIgnore> + <test.env.db.hibernate.ddl.auto> </test.env.db.hibernate.ddl.auto> + <test.env>mysql</test.env> + </properties> + <build> + <plugins> + <plugin> + <!-- Documentation: http://maven.apache.org/plugins/maven-surefire-plugin/ --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.8.1</version> + <configuration> + <argLine>-Xmx512m -Xms512m</argLine> + <testNGArtifactName>none:none</testNGArtifactName> + <includes> + <include>**/AllTestsOlatCoreJunit4.java</include> + <include>**/AllTestsJunit4.java</include> + </includes> + </configuration> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <id>copy-resources-4-mysqlunittests</id> + <!-- hook in to copy maven.build.properties to allow test and integration-test phase run properly --> + <phase>generate-test-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${basedir}/target/test-classes</outputDirectory> + <resources> + <resource> + <!-- place resources you like to get filtered an copied --> + <directory>src/test/profile/${test.env}</directory> + <includes> + <include>olat.local.properties</include> + </includes> + <filtering>true</filtering> + </resource> + <resource> + <!-- place resources you like to get filtered an copied --> + <directory>src/main/resources/database/mysql</directory> + <includes> + <include>setupDatabase.sql</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <profile> + <id>clean-mysql-dbsetup</id> + <activation> + <property> + <name>with-mysql</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <id>copy-resources-4-clean-mysql-dbsetup</id> + <phase>generate-test-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${basedir}/target/test-classes</outputDirectory> + <resources> + <resource> + <!-- place resources you like to get filtered an copied --> + <directory>src/main/resources/database/mysql</directory> + <includes> + <include>setupDatabase.sql</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>sql-maven-plugin</artifactId> + <version>1.4</version> + + <dependencies> + <dependency> + <!-- DO NOT UPDATE! --> + <!-- Due to our special setup where we use the jdbc driver to convert + from utf-8 to iso we cannot update this lib at the moment. --> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.0.8</version> + </dependency> + </dependencies> + + <!-- common configuration shared by all executions --> + <configuration> + <driver>com.mysql.jdbc.Driver</driver> + <url>jdbc:mysql://localhost:${test.env.db.host.port}/${test.env.db.name}</url> + <username>${test.env.db.user}</username> + <password>${test.env.db.pass}</password> + <!-- You can comment out username/password configurations and + have maven to look them up in your settings.xml using ${settingsKey} + + <settingsKey>sensibleKey</settingsKey>--> + <!--all executions are ignored if -Dmaven.test.skip=true--> + <skip>${maven.test.skip}</skip> + </configuration> + + <executions> + <execution> + <id>drop-db-before-test</id> + <phase>process-test-resources</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <!-- need another database to drop the targeted one --> + <url>jdbc:mysql://localhost:${test.env.db.host.port}/olat</url> + <autocommit>true</autocommit> + <sqlCommand>drop database ${test.env.db.name}</sqlCommand> + <!-- ignore error when database is not avaiable --> + <onError>continue</onError> + </configuration> + </execution> + + <execution> + <id>create-db</id> + <phase>process-test-resources</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <url>jdbc:mysql://localhost:${test.env.db.host.port}/olat</url> + <!-- no transaction --> + <autocommit>true</autocommit> + <sqlCommand>create database ${test.env.db.name}</sqlCommand> + </configuration> + </execution> + + <execution> + <id>create-schema</id> + <phase>process-test-resources</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <autocommit>true</autocommit> + <srcFiles> + <srcFile>target/test-classes/setupDatabase.sql</srcFile> + </srcFiles> + </configuration> + </execution> +<!-- + <execution> + <id>create-data</id> + <phase>process-test-resources</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <orderFile>ascending</orderFile> + <fileset> + <basedir>${basedir}</basedir> + <includes> + <include>src/test/sql/test-data2.sql</include> + <include>src/test/sql/test-data1.sql</include> + </includes> + </fileset> + </configuration> + </execution> +--> + <!-- drop db after test --> + <execution> + <id>drop-db-after-test</id> + <!-- there is no post-test phase, the next phase after "test" is "prepare-package" + for integration tests running against mysql generated via setupDatabase.sql there is need + to bind a similar drop/create/schema/drop to pre-integration-test and post-integration-test --> + <phase>prepare-package</phase> + <goals> + <goal>execute</goal> + </goals> + <configuration> + <autocommit>true</autocommit> + <sqlCommand>drop database ${test.env.db.name}</sqlCommand> + </configuration> + </execution> + </executions> + </plugin> + + + + </plugins> + </build> + </profile> + <profile> + <!-- activate this profile to unzip two tomcats instances for cluster setup, which are the configured and used with profile seleniumtests + bind to phase initialize and execute goal unpack + ... initialize is an early phase, so that unpacking does not overwrite resources copied over to the tomcats. --> + <id>install-tomcats</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.2</version> + <executions> + <execution> + <id>install-tomcat-one</id> + <phase>validate</phase> + <goals> + <goal>unpack + </goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>org.olat.testutils</groupId> + <artifactId>zipped-tomcat6x</artifactId> + <version>1.0</version> + <type>zip</type> + <overWrite>true</overWrite> + <outputDirectory>${container.tomcat.one.install.dir}</outputDirectory> + </artifactItem> + </artifactItems> + <!-- other configurations here --> + </configuration> + </execution> + <execution> + <id>install-tomcat-two</id> + <!-- bind to initialize, that tomcats are unpacked before resources are copied over --> + <phase>validate</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>org.olat.testutils</groupId> + <artifactId>zipped-tomcat6x</artifactId> + <version>1.0</version> + <type>zip</type> + <overWrite>true</overWrite> + <outputDirectory>${container.tomcat.two.install.dir}</outputDirectory> + </artifactItem> + </artifactItems> + <!-- other configurations here --> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <profile> + <id>debug</id> + <properties> + <skipTests>true</skipTests> + <skipITs>true</skipITs> + <cargo.container.wait>true</cargo.container.wait> + </properties> + </profile> + + + <profile> + <!-- activate this profile to run Selenium based Integration Tests against a cluster running locally + configures: + - surefire-plugin to include none of the IntegrationTests + - failsafe-plugin to include Seleniumtests via testng.xml + + in general hooks into: (please check the profile execution against the docu) + - initialize + ... cleans the tomcats working directories. + - generate-resources + ... resources-plugin to copy the maven.build.properties and selenium specific additionalUserContext.xml and specific olat.local.properties for tomcat-one and tomcat-two. + ... copies jms configuration + - generate-test-resources + ... antrun-plugin to transform the olat page sets into selenium JS, creates the olat-user-extension.js file for selenium server start. + ... resources-plugin to copy the maven.build.properties to the test-classes tree, would be needed for failsafe *ITCase tests. + - pre-integration-test + ... selenium-maven-plugin to start the selenium server (runs in the background and logs output to target/selenium/server.log) using the generated olat-user-extension.js + ... starts an active mq jms for cluster instances. + ... cargo-maven2-plugin deploying the asset OLAT-LMS into two tomcats which must be installed beforehand with (-Pinstall-tomcats) + - post-integration-test + ... cargo-maven2-plugin stops the started tomcat(s) + ... stops active mq + ... stops selenium + --> + <id>seleniumtests</id> + <properties> + <!-- seleniumtests are started with the command mvn verify -Pseleniumtests --> + <skipTests>false</skipTests> + <skipITs>false</skipITs> + </properties> + <build> + + <plugins> + + <plugin> + <!-- Documentation: http://maven.apache.org/plugins/maven-surefire-plugin/ --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.7.2</version> + <configuration> + <includes> + <include>none</include> + </includes> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.6</version> + <executions> + <execution> + <phase>generate-test-resources</phase> + <configuration> + <target unless="maven.test.skip"> + <echo message="Generate ../target/olat-user-extensions.js for Seleniumserverstart"/> + <xslt in="${basedir}/src/test/profile/selenium/ui-map/olat-ui-map.xml" out="${basedir}/target/generated_combined_olat-ui-map.xml" style="${basedir}/src/test/profile/selenium/ui-map/resources/resolve_includes.xsl"/> + <xslt in="${basedir}/target/generated_combined_olat-ui-map.xml" out="${basedir}/target/olat-ui-map.js" style="${basedir}/src/test/profile/selenium/ui-map/resources/gen_olat-ui-map.xsl"> + </xslt> + <concat destfile="${basedir}/target/olat-user-extensions.js"> + <fileset file="${basedir}/target/olat-ui-map.js"/> + <fileset file="${basedir}/src/test/profile/selenium/ui-map/resources/rollups.js"/> + </concat> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <id>tomcat-one-server_xml</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${container.tomcat.one.home}/conf/</outputDirectory> + <resources> + <resource> + <directory>src/test/profile/cluster/tomcat-one/conf</directory> + <includes> + <include>server.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>tomcat-two-server_xml</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${container.tomcat.two.home}/conf/</outputDirectory> + <resources> + <resource> + <directory>src/test/profile/cluster/tomcat-two/conf</directory> + <includes> + <include>server.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>seleniumtests-config-tomcat-one</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${container.tomcat.one.home}/lib/</outputDirectory> + <overwrite>true</overwrite> + <resources> + <!-- olat.local.properties with different environments + typically meant for hsql / mysql / etc. --> + <resource> + <directory>src/test/profile/cluster/tomcat-one/lib</directory> + <includes> + <include>olat.local.properties</include> + <include>treecache.xml</include> + </includes> + <filtering>true</filtering> + </resource> + <!-- Users to be created on OLAT startup for selenium testcases are configured in this file --> + <resource> + <directory>${selenium.config.files.path}</directory> + <includes> + <include>additionalUserContext.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>seleniumtests-config-activemq</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>cargo/</outputDirectory> + <overwrite>true</overwrite> + <resources> + <resource> + <directory>src/test/profile/cluster/activemq</directory> + <includes> + <include>activemq.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>seleniumtests-config-tomcat-two</id> + <phase>initialize</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${container.tomcat.two.home}/lib/</outputDirectory> + <overwrite>true</overwrite> + <resources> + <resource> + <directory>src/test/profile/cluster/tomcat-two/lib</directory> + <includes> + <include>olat.local.properties</include> + <include>treecache.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + <execution> + <id>seleniumtests-config-misc</id> + <phase>process-test-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${basedir}/target/test-classes</outputDirectory> + <resources> + <resource> + <directory>${selenium.config.files.path}</directory> + <includes> + <include>defaultcontext.xml</include> + <include>testng.xml</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.activemq.tooling</groupId> + <artifactId>maven-activemq-plugin</artifactId> + <version>5.3.0</version> + <executions> + <execution> + <phase>pre-integration-test</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <configUri>xbean:file:${basedir}/cargo/activemq.xml</configUri> + <fork>true</fork> + <systemProperties> + <property> + <name>org.apache.activemq.default.directory.prefix</name> + <value>./target/</value> + </property> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>selenium-maven-plugin</artifactId> + <version>1.1</version> + <executions> + <execution> + <phase>pre-integration-test</phase> + <goals> + <goal>start-server</goal> + </goals> + <configuration> + <!-- run selenium server in background and log output ${basedir}target/server.log. + Append to ${basedir}/target/selenium/user-extensions.js --> + <background>true</background> + <logOutput>true</logOutput> + <userExtensions>${basedir}/target/olat-user-extensions.js</userExtensions> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>2.7.2</version> + <configuration> + <suiteXmlFiles> + <!-- Seleniumtests run with testng, the included tests are defined in the following suite xml. + The file is located in src/test/resources/testng.xml. Dependencies of tests are defined + over annotations. --> + <suiteXmlFile>target/test-classes/testng.xml</suiteXmlFile> + </suiteXmlFiles> + <testFailureIgnore>true</testFailureIgnore> + </configuration> + <executions> + <execution> + <id>integration-test</id> + <goals> + <goal>integration-test</goal> + </goals> + </execution> + <execution> + <id>verify</id> + <goals> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.cargo</groupId> + <artifactId>cargo-maven2-plugin</artifactId> + <configuration>Selenium + <container> + <containerId>tomcat6x</containerId> + <timeout>${cargo.container.timeout}</timeout> + </container> + </configuration> + <executions> + <execution> + <id>tomcat-one-start</id> + <phase>pre-integration-test</phase> + <goals> + <goal>start</goal> + </goals> + <configuration> + <wait>false</wait> + <container> + <containerId>tomcat6x</containerId> + <type>installed</type> + <home>${container.tomcat.one.home}</home> + </container> + <configuration> + <type>existing</type> + <home>${container.tomcat.one.home}</home> + <properties> + <cargo.servlet.port>${container.tomcat.one.port}</cargo.servlet.port> + <cargo.logging>high</cargo.logging> +<!-- + <cargo.jvmargs> + "-Xdebug" "-Xrunjdwp:transport=dt_socket,address=4646,server=y,suspend=n" + </cargo.jvmargs> +--> + </properties> + <deployables> + <deployable> + <groupId>org.olat</groupId> + <artifactId>OLAT-LMS</artifactId> + <type>war</type> + <properties> + <context>olat</context> + </properties> + <pingURL>http://localhost:${container.tomcat.one.port}/cargocpc/</pingURL> + <pingTimeout>300000</pingTimeout> + </deployable> + </deployables> + </configuration> + </configuration> + </execution> + <execution> + <id>tomcat-one-stop</id> + <phase>post-integration-test</phase> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <configuration> + <type>existing</type> + <home>${container.tomcat.one.home}</home> + </configuration> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.cargo</groupId> + <artifactId>cargo-maven2-plugin</artifactId> + <configuration> + <container> + <containerId>tomcat6x</containerId> + <timeout>${cargo.container.timeout}</timeout> + </container> + </configuration> + <executions> + <execution> + <id>tomcat-two-start</id> + <phase>pre-integration-test</phase> + <goals> + <goal>start</goal> + </goals> + <configuration> + <wait>${cargo.container.wait}</wait> + <container> + <containerId>tomcat6x</containerId> + <!--<zipUrlInstaller> + <url>http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.29/bin/apache-tomcat-6.0.29.zip</url> + <installDir>${container.tomcat.one.install.dir}</installDir> + </zipUrlInstaller>--> + <type>installed</type> + <home>${container.tomcat.two.home}</home> + </container> + <configuration> + <type>existing</type> + <home>${container.tomcat.two.home}</home> + <properties> + <cargo.servlet.port>${container.tomcat.two.port}</cargo.servlet.port> + <cargo.logging>high</cargo.logging> +<!-- + <cargo.jvmargs> + "-Xdebug" "-Xrunjdwp:transport=dt_socket,address=5656,server=y,suspend=n" + </cargo.jvmargs> +--> + </properties> + <deployables> + <deployable> + <groupId>org.olat</groupId> + <artifactId>OLAT-LMS</artifactId> + <type>war</type> + <properties> + <context>olat</context> + </properties> + <pingURL>http://localhost:${container.tomcat.two.port}/cargocpc/</pingURL> + <pingTimeout>300000</pingTimeout> + </deployable> + </deployables> + </configuration> + </configuration> + </execution> + <execution> + <id>tomcat-two-stop</id> + <phase>post-integration-test</phase> + <goals> + <goal>stop</goal> + </goals> + <configuration> + <configuration> + <type>existing</type> + <home>${container.tomcat.two.home}</home> + </configuration> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-clean-plugin</artifactId> + <version>2.4.1</version> + <executions> + <execution> + <id>clean-tomcat-directories</id> + <phase>initialize</phase> + <goals> + <goal> + clean + </goal> + </goals> + <configuration> + <excludeDefaultDirectories>true</excludeDefaultDirectories> + <filesets> + <fileset> + <directory>${container.tomcat.one.home}/webapps/</directory> + <includes> + <include>olat.war</include> + <include>**/olat/**</include> + </includes> + </fileset> + <fileset> + <directory>${container.tomcat.one.home}/work/</directory> + <includes> + <include>**/SESSIONS.ser</include> + </includes> + </fileset> + <fileset> + <directory>${container.tomcat.two.home}/webapps/</directory> + <includes> + <include>olat.war</include> + <include>**/olat/**</include> + </includes> + </fileset> + <fileset> + <directory>${container.tomcat.two.home}/work/</directory> + <includes> + <include>**/SESSIONS.ser</include> + </includes> + </fileset> + </filesets> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> <repositories> <repository> @@ -455,42 +1337,8 @@ <artifactId>maven-site-plugin</artifactId> <version>2.2</version> </plugin> - <!-- Surefire plugin used to execute unit tests. - "mvn -DskipTests=false test" to run all tests - "mvn -DskipTests=false -Dtest=UserTest test" to execute a specific test --> - <plugin> - <!-- Documentation: http://maven.apache.org/plugins/maven-surefire-plugin/ --> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>2.5</version> - <configuration> - <testFailureIgnore>true</testFailureIgnore> - <skipTests>${skipTests}</skipTests> - <argLine>-XX:MaxPermSize=256m -Xmx1024m -Xms1024m</argLine> - <systemPropertyVariables> - <java.io.tmpdir>${project.build.directory}/olatdata</java.io.tmpdir> - </systemPropertyVariables> - <excludes> - <!-- TODO:gs --> - <exclude>**/TestTable.java</exclude> - <exclude>**/TestUser*</exclude> - <exclude>**/TestIdentity.java</exclude> - <exclude>**/TestTextCase*</exclude> - <exclude>**/*PerformanceTest.java</exclude> - </excludes> - <includes> - <include>**/AllTestsOlatCoreJunit4.java</include> - <include>**/AllTestsJunit4.java</include> - </includes> - - <!-- To run a single test add -Dtest=TestClass... test mvn -Dtest=TestSquare,TestCi*le - test NOTE: Running a single test runs always twice, no idea why To run the - OLAT Test suite run: mvn -Dtest=AllTestsJunit4 test --> - </configuration> - </plugin> <plugin> - <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <executions> @@ -518,7 +1366,6 @@ </configuration> </execution> </executions> - </plugin> <!-- mvn org.mortbay.jetty:jetty-maven-plugin:run will start olat with jetty @@ -1478,7 +2325,20 @@ <!-- fxdiff: FXOLAT-243 only for testing purpose --> <scope>test</scope> </dependency> - + <!-- START selenium tests dependencies --> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>5.14</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.seleniumhq.selenium.client-drivers</groupId> + <artifactId>selenium-java-client-driver</artifactId> + <version>${selenium-client.version}</version> + <scope>test</scope> + </dependency> + <!-- END selenium tests dependencies --> diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml index b5843124dd759f1e1f0eb4f7dcede49556d93e1e..0f9d74a0474ebb86db0d0826494eeb9a5d648f9b 100644 --- a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml +++ b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml @@ -214,7 +214,7 @@ <!-- TODO: may update to version 2.x of ehcache which only has the region.factory_class property--> <!-- <entry key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</value></entry> --> <entry key="hibernate.cache.provider_class"><value>${hibernate.caching.singlevm.class}</value></entry> - <entry key="hibernate.cache.use_query_cache"><value>true</value></entry> + <entry key="hibernate.cache.use_query_cache"><value>${hibernate.caching.use.query.cache}</value></entry> <entry key="hibernate.cache.use_second_level_cache"><value>${hibernate.use.second.level.cache}</value></entry> <!-- TODO: ask christian, does this need to be false on SV mode? --> <!-- <entry key="hibernate.cache.region.factory_class">org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory</value></entry> --> <entry key="hibernate.cache.region.factory_class"><value>${hibernate.caching.cluster.class}</value></entry> diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties index aab8d05f983b2571b6f8b1e7216ff504bd063207..b51397b4e1f7e51221163281faf50446881ec2a9 100644 --- a/src/main/resources/serviceconfig/olat.properties +++ b/src/main/resources/serviceconfig/olat.properties @@ -447,6 +447,7 @@ codepoint_server.enabled=false hibernate.caching.singlevm.class=net.sf.ehcache.hibernate.EhCacheProvider #hibernate.caching.cluster.class=org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory hibernate.caching.cluster.class= +hibernate.caching.use.query.cache=true hibernate.use.second.level.cache=true ##### diff --git a/src/test/HOWTO-UnitTesting b/src/test/HOWTO-UnitTesting new file mode 100644 index 0000000000000000000000000000000000000000..2cb2c0f0f147cf9a2a0069ca3f51803705fd0e5e --- /dev/null +++ b/src/test/HOWTO-UnitTesting @@ -0,0 +1,52 @@ +Unittesting with Spring and Junit4 + +@autor: Guido Schnider - 19.05.2010 +------------------------------------------------------------- + +(Wikipedia http://en.wikipedia.org/wiki/Unit_testing) +In computer programming, unit testing is a software verification and validation method in which a programmer tests if individual units of source code are fit for use. +A unit is the smallest testable part of an application. In procedural programming a unit may be an individual function or procedure. + +Because some classes may have references to other classes, testing a class can frequently spill over into testing another class. +A common example of this is classes that depend on a database: in order to test the class, the tester often writes code that interacts with the database. +This is a mistake, because a unit test should usually not go outside of its own class boundary. + + +Eclipse setup +----------------------------------- +If you have problems running the junit tests (Errors like: Could not find olat.propeties file). Check your build path for the src/test/java settings that it includes +ALL files and not only *.java classes! + +To achive this there are some different approaches: + +1: You like to test code which does not depend on any spring beans or any other olat framework stuff + +Solution: Use the junit4 annotations @RunWith for the class and @Test for every method you like to test +----------------------------------- + +@RunWith(JUnit4.class) +public class AddBaseURLToMediaRelativeURLFilterTest {... + +@Test +public void testPlainText() {... +----------------------------------- + +2: You like to test code which includes managers/modules that are spring beans you can use this setup: + +----------------------------------- +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = { + "/org/olat/core/test/_spring/yourSpringContext.xml"}) + +public class YourTestClass {... + +------------------------------------- + +The Springcontext gets loaded and you can use @Autowire or access directly the "applicationContext" var and do you testing + +3: If you need more stuff from the framework like Coordinator or database access in your code you can use the OlatcoreTestCaseWithMocking which +already has some mocked stuff inside (Coordinator.getEventBus() calls) or create your own mocks based on the example. The library we use for mocking is +Mockito (http://mockito.org/) +When you run all tests in a suite, the spring context gets cached and only loaded once for better performance. But if you load the same spring beans twice, +the beans will not get overwritten and instead they get created again and a new instance gets assigned for e.g. a singleton. + diff --git a/src/test/java/org/olat/test/demo/CourseImportTest.java b/src/test/java/org/olat/test/demo/CourseImportTest.java new file mode 100644 index 0000000000000000000000000000000000000000..878fffb5130f6ce8baf6fbdda04f364ce8699607 --- /dev/null +++ b/src/test/java/org/olat/test/demo/CourseImportTest.java @@ -0,0 +1,37 @@ +package org.olat.test.demo; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * + * @author eglis + * + */ +public class CourseImportTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "/CourseImportCourse.zip"; + + public void testCourseImport() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + String courseTitle = "CourseImportTestCourse-"+System.currentTimeMillis(); + WorkflowHelper.importCourse(f, courseTitle, "Whatever right?"); + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(courseTitle); + courseRun.close(courseTitle); + + } + +} diff --git a/src/test/java/org/olat/test/demo/CourseOpenCloseTest.java b/src/test/java/org/olat/test/demo/CourseOpenCloseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94bf42b24854508fede9b6385c04ba3caef016f1 --- /dev/null +++ b/src/test/java/org/olat/test/demo/CourseOpenCloseTest.java @@ -0,0 +1,21 @@ +package org.olat.test.demo; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +public class CourseOpenCloseTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = Context.DEMO_COURSE_NAME_1; + + public void testCourseOpenClose() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + //context.checkSeleniumServerStarted(); + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + CourseRun courseRun = workflow.getLearningResources().showCourseContent(COURSE_NAME); + courseRun.close(COURSE_NAME); + } +} diff --git a/src/test/java/org/olat/test/demo/OpenForumThreadTest.java b/src/test/java/org/olat/test/demo/OpenForumThreadTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1eaceec9c62ce36187732d8d7ccb7f2baf21c54b --- /dev/null +++ b/src/test/java/org/olat/test/demo/OpenForumThreadTest.java @@ -0,0 +1,26 @@ +package org.olat.test.demo; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +public class OpenForumThreadTest extends BaseSeleneseTestCase { + + public void setUp() throws Exception { + Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + } + + public void testShowCourseContent() throws Exception { + selenium = Context.getContext().createSeleniumAndLogin(); //login as the default admin user + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_1); + Forum forum = courseRun.selectForum("Forum"); + forum.openNewTopic("abc", "MESSAGE BODY"); + courseRun.selectForum("Forum").viewTopic("abcd"); + + workflow.logout(); + } +} diff --git a/src/test/java/org/olat/test/demo/SeleniumDemo1Test.java b/src/test/java/org/olat/test/demo/SeleniumDemo1Test.java new file mode 100644 index 0000000000000000000000000000000000000000..e1b23ec3715d5fb11f8aa21bb53051353e9d8513 --- /dev/null +++ b/src/test/java/org/olat/test/demo/SeleniumDemo1Test.java @@ -0,0 +1,58 @@ +package org.olat.test.demo; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Demo test class. + * Uses selenium commands calls and OLAT testing framework. + * + * @author Lavinia Dumitrescu + * + * @deprecated Do not use selenium commands directly, + * use the abstraction layer api <code> org.olat.test.util.selenium.olatapi </code> instead. + * + */ +public class SeleniumDemo1Test extends BaseSeleneseTestCase { + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + //selenium = context.createSelenium(); + } + + /** + * Login, go to Learning resources, select Courses, select "Demo Course", Show content, + * open Course Editor, insert a Forum course element, publish course, logout. + * + * @throws Exception + */ + public void testCourseEditing() throws Exception { + + selenium = Context.getContext().createSeleniumAndLogin(); //login as the default admin user + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_courses()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=Demo Course)"); + selenium.waitForPageToLoad("30000"); + + selenium.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertForum()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + selenium.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_selectall()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_finish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/demo/SeleniumDemo2Test.java b/src/test/java/org/olat/test/demo/SeleniumDemo2Test.java new file mode 100644 index 0000000000000000000000000000000000000000..9195dcecf3cce9279f5d9c7c966f92d745b9d6e3 --- /dev/null +++ b/src/test/java/org/olat/test/demo/SeleniumDemo2Test.java @@ -0,0 +1,67 @@ +package org.olat.test.demo; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Demo test class. + * Uses the OLAT testing framework, including the OLAT abstraction layer. + * + * <br/> + * Test setup: none, since any OLAT instance has a "Demo Course" per default. + * <br/> + * Test case: <br/> + * - login, <br/> + * - go to Learning resources, <br/> + * - search for "Demo Course", <br/> + * - Show content, <br/> + * - open Course Editor, <br/> + * - insert a Forum course element, <br/> + * - publish course, <br/> + * - logout. + * + * @author Lavinia Dumitrescu + * + */ +public class SeleniumDemo2Test extends BaseSeleneseTestCase { + + private static final String COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private static final String FORUM_NAME = "Special Forum Name"; + + public void setUp() throws Exception { + //each test has to setup a context + Context.setupContext(getFullName(), SetupType.SINGLE_VM); + } + + /** + * Login, go to Learning resources, select Courses, select "Demo Course", Show content, + * open Course Editor, insert a Forum course element, publish course, logout. + * + * @throws Exception + */ + public void testCourseEditing() throws Exception { + //Get a workflow object for the default administrator user. + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + //go to learning resources, search and show the course named COURSE_NAME, get a CourseRun object + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + + //go to the course editor + CourseEditor courseEditor = courseRun.getCourseEditor(); + + //insert a course element of type FORUM, with a specified title + CourseElementEditor courseElementEditor = courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, FORUM_NAME); + assertTrue(courseElementEditor.isTextPresent(FORUM_NAME)); + + //publish course + courseEditor.publishCourse(); + + //logout + workflow.logout(); + } +} diff --git a/src/test/java/org/olat/test/demo/SeleniumTestingDemoTest3_html.html b/src/test/java/org/olat/test/demo/SeleniumTestingDemoTest3_html.html new file mode 100644 index 0000000000000000000000000000000000000000..bb85b75f9f5a4cf3e15b4b2cf38f6a48401383af --- /dev/null +++ b/src/test/java/org/olat/test/demo/SeleniumTestingDemoTest3_html.html @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>SeleniumTestingDemoTest3_html</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">SeleniumTestingDemoTest3_html</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>administrator</td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::password()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>nightly1</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Learning</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Demo Course)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Demo</td> + <td>Demo</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/demo/ShowCourseContentTest.java b/src/test/java/org/olat/test/demo/ShowCourseContentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a98a208a5f48395f4df6445feee8ed1aafc0c248 --- /dev/null +++ b/src/test/java/org/olat/test/demo/ShowCourseContentTest.java @@ -0,0 +1,33 @@ +package org.olat.test.demo; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +public class ShowCourseContentTest extends BaseSeleneseTestCase { + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + //selenium = context.createSelenium(); + } + + /** + * Login, go to learning resources and show content of "Demo Course", logout. + * @throws Exception + */ + public void testShowCourseContent() throws Exception { + + selenium = Context.getContext().createSeleniumAndLogin(); //login as the default admin user + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_courses()"); + selenium.waitForPageToLoad("30000"); + //selenium.click("ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Demo Course)"); + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=Demo Course)"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Demo")); + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/demo/package.html b/src/test/java/org/olat/test/demo/package.html new file mode 100644 index 0000000000000000000000000000000000000000..aa234280e321949619a795d50b34bcb309fc1a1f --- /dev/null +++ b/src/test/java/org/olat/test/demo/package.html @@ -0,0 +1,12 @@ +<html> +<head> +</head> + +<body> + +Contains simple demo tests. +<br/> +They do not belong to the regresssion test suite. + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/demo/selenium.olat.uzh.context.xml b/src/test/java/org/olat/test/demo/selenium.olat.uzh.context.xml new file mode 100644 index 0000000000000000000000000000000000000000..c5baedb415e9e10e461e38531b76c67fb6add1b2 --- /dev/null +++ b/src/test/java/org/olat/test/demo/selenium.olat.uzh.context.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> + +<!-- rename in customcontext.xml and add to the same location as defaultcontext.xml --> +<!-- context for testing against a running olat instance e.g. http://demo.olat.org/demo/dmz/, with selenium server running locally --> +<beans> + <bean class="org.olat.test.util.setup.context.SeleniumLocallyContext" id="seleniumcontext"> + <property name="config"> + <map> + <entry key="seleniumHost" value="localhost"/> + <entry key="instanceId" value="olat"/> + <entry key="jmsBrokerUrl" value="tcp://localhost:61616"/> + <entry key="adminUsername" value="administrator"/> + <entry key="adminPassword" value="olat"/> + <entry key="authorUsername" value="author"/> + <entry key="authorPassword" value="test"/> + <entry key="studentUsername" value="test"/> + <entry key="studentPassword" value="test"/> + <entry key="guestUsername" value="guest"/> + <entry key="guestPassword" value="guest"/> + <entry key="singleVmOlatUrl" value="http://demo.olat.org/demo/dmz/"/> + <entry key="multiVmOlatUrl1" value="http://demo.olat.org/demo/dmz/"/> + <entry key="multiVmOlatUrl2" value="http://demo.olat.org/demo/dmz/"/> +<!-- <entry key="browserId" value="*firefox /usr/lib/mozilla-firefox/firefox"/> --> + </map> + </property> + </bean> +</beans> diff --git a/src/test/java/org/olat/test/file_resources/CourseImportCourse.zip b/src/test/java/org/olat/test/file_resources/CourseImportCourse.zip new file mode 100644 index 0000000000000000000000000000000000000000..abb46f75e4976c8d023498b5a8f00a7375a249bb Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/CourseImportCourse.zip differ diff --git a/src/test/java/org/olat/test/file_resources/Course_with_all_bb.zip b/src/test/java/org/olat/test/file_resources/Course_with_all_bb.zip new file mode 100644 index 0000000000000000000000000000000000000000..cbd89c9a28ddebc3ba749ace16b8ea6c2d498317 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Course_with_all_bb.zip differ diff --git a/src/test/java/org/olat/test/file_resources/DemoCourse.zip b/src/test/java/org/olat/test/file_resources/DemoCourse.zip new file mode 100644 index 0000000000000000000000000000000000000000..a3023c30845d40cf70850c1ef9b1da063d64460f Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/DemoCourse.zip differ diff --git a/src/test/java/org/olat/test/file_resources/Mp3.mp3 b/src/test/java/org/olat/test/file_resources/Mp3.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5f115a8a336f1f8c2a34df9e3d5b45c02c198845 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Mp3.mp3 differ diff --git a/src/test/java/org/olat/test/file_resources/OLATteam.jpg b/src/test/java/org/olat/test/file_resources/OLATteam.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf70e55b5b302ce2f146ebd03ae277eb0b2edad3 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/OLATteam.jpg differ diff --git a/src/test/java/org/olat/test/file_resources/Pdf.pdf b/src/test/java/org/olat/test/file_resources/Pdf.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Pdf.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/Word.doc b/src/test/java/org/olat/test/file_resources/Word.doc new file mode 100644 index 0000000000000000000000000000000000000000..83d71142f86108298679e1ffec446dfa066f7ffa Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Word.doc differ diff --git a/src/test/java/org/olat/test/file_resources/Word_new.docx b/src/test/java/org/olat/test/file_resources/Word_new.docx new file mode 100644 index 0000000000000000000000000000000000000000..6dc7bce3dcbdc9bcbecd19f98ee40d94606e948b Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/Word_new.docx differ diff --git a/src/test/java/org/olat/test/file_resources/cptest.html b/src/test/java/org/olat/test/file_resources/cptest.html new file mode 100644 index 0000000000000000000000000000000000000000..99e1c2de4f16e124b726a63392abc062bb2a7742 --- /dev/null +++ b/src/test/java/org/olat/test/file_resources/cptest.html @@ -0,0 +1,12 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> +<title>cptest</title> +</head> + +<body> +cptest.html +</body> + +</html> diff --git a/src/test/java/org/olat/test/file_resources/first.html b/src/test/java/org/olat/test/file_resources/first.html new file mode 100644 index 0000000000000000000000000000000000000000..a8c8d98f986168da822be3741251735cf6ffd8d7 --- /dev/null +++ b/src/test/java/org/olat/test/file_resources/first.html @@ -0,0 +1,6 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head><meta name="generator" content="olat-tinymce-2"> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +</head><body><div align="center"><span style="font-size: x-large; color: #993300">This is the first page</span><br /></div></body></html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/file_resources/firstmedia.flv b/src/test/java/org/olat/test/file_resources/firstmedia.flv new file mode 100644 index 0000000000000000000000000000000000000000..5dd6f973337c674a4b3a71136cf5f85f73838e39 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/firstmedia.flv differ diff --git a/src/test/java/org/olat/test/file_resources/handBackTopic1.pdf b/src/test/java/org/olat/test/file_resources/handBackTopic1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handBackTopic1.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/handBackTopic3.pdf b/src/test/java/org/olat/test/file_resources/handBackTopic3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handBackTopic3.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/handInTopic1.pdf b/src/test/java/org/olat/test/file_resources/handInTopic1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handInTopic1.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/handInTopic2.pdf b/src/test/java/org/olat/test/file_resources/handInTopic2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handInTopic2.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/handInTopic3.pdf b/src/test/java/org/olat/test/file_resources/handInTopic3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handInTopic3.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/handInTopic4.pdf b/src/test/java/org/olat/test/file_resources/handInTopic4.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274601436526fc4e36dd7750d7adf429e5d3505 Binary files /dev/null and b/src/test/java/org/olat/test/file_resources/handInTopic4.pdf differ diff --git a/src/test/java/org/olat/test/file_resources/second.html b/src/test/java/org/olat/test/file_resources/second.html new file mode 100644 index 0000000000000000000000000000000000000000..bbbbd7706ba5dad8f8f03be1d98a59d18a1ac877 --- /dev/null +++ b/src/test/java/org/olat/test/file_resources/second.html @@ -0,0 +1,6 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head><meta name="generator" content="olat-tinymce-2"> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +</head><body><div align="center"><span style="font-size: x-large; color: #993300">This is the second page (from resource folder)</span><br /></div></body></html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/administration/ASetupFNTestCase.java b/src/test/java/org/olat/test/functional/administration/ASetupFNTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..0eddfaa69261fdda27db3050d9aa477f90e94606 --- /dev/null +++ b/src/test/java/org/olat/test/functional/administration/ASetupFNTestCase.java @@ -0,0 +1,75 @@ +package org.olat.test.functional.administration; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * This is the very first test that should run in the selenium test suite. + * It imports the necessary assets, and executes some cleanup tasks. + * + * @author lavinia + * + */ +public class ASetupFNTestCase extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "DemoCourse.zip"; + + + + @Override + public void setUp() throws Exception { + Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + } + + /** + * Import demo course. + * @throws Exception + */ + public void testImportDemoCourses() throws Exception { + + //check if "Demo Course" already available, if so return + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + if(workflow.getLearningResources().searchResource(Context.DEMO_COURSE_NAME_1, "")!=null) { + return; + } + + //import test course + File file = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", file); + assertTrue("file "+file.getAbsolutePath()+" not found!", file.exists()); + + WorkflowHelper.importCourse(file, Context.DEMO_COURSE_NAME_1, "demo course description"); + WorkflowHelper.addOwnerToLearningResource("author", Context.DEMO_COURSE_NAME_1); + + workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + LRDetailedView lRDetailedView = workflow.getLearningResources().searchMyResource(Context.DEMO_COURSE_NAME_1); + lRDetailedView.removeOwner(Context.getContext().getStandardAdminOlatLoginInfos(1).getUsername()); + } + + /** + * Deletes archives from personal folder, if any. + */ + public void testCleanupArchiveFolder() { + testCleanupArchiveFolder(Context.getContext().getStandardAdminOlatLoginInfos(1)); + testCleanupArchiveFolder(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + } + + /** + * deletes Personal folder/private/archive. + * @param olatLoginInfos + */ + private void testCleanupArchiveFolder(OlatLoginInfos olatLoginInfos) { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(olatLoginInfos); + Folder folder = workflow.getHome().getPersonalFolder(); + folder.selectFileOrFolder("private"); + folder.deleteItem("archive"); + } +} diff --git a/src/test/java/org/olat/test/functional/administration/InfoMessageClusterTest.java b/src/test/java/org/olat/test/functional/administration/InfoMessageClusterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..376d56fe8c92b2c772f5bf0943b9e71d6f514c75 --- /dev/null +++ b/src/test/java/org/olat/test/functional/administration/InfoMessageClusterTest.java @@ -0,0 +1,51 @@ +package org.olat.test.functional.administration; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.admin.Administration; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * test info message occurences when changed on other node + * + * @author Guido + * + */ +public class InfoMessageClusterTest extends BaseSeleneseTestCase { + + private final String MESSAGE_1 = "may the force be with you!"; + + public void testInfoMessage() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OLATWorkflowHelper workflow1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + + Administration admin1 = workflow1.getAdministration(); + admin1.editInfoMessage(MESSAGE_1); + assertTrue("Assert that the info message was set.", admin1.hasInfoMessage(MESSAGE_1)); + + workflow2.logout(); + assertTrue(workflow2.getSelenium().isTextPresent(MESSAGE_1)); + + workflow1.logout(); + assertTrue(workflow1.getSelenium().isTextPresent(MESSAGE_1)); + + //TODO: change message + + //TODO: reset message + + } + + @Override + protected void cleanUpAfterRun() { + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + workflow1.getAdministration().editInfoMessage(""); + } + + + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/AssessmentWithCodepointsTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/AssessmentWithCodepointsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bff4112abb0103d48cb16aa7ada31388340f34f3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/AssessmentWithCodepointsTest.java @@ -0,0 +1,341 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ + +package org.olat.test.functional.codepoints.cluster; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + + /** + * Tests the Assessment (AssessmentTool, TestRun, EfficiencyStatement) - in cluster mode. + * <br/> + * + * Test setup: <br/> + * Expects a special "AssessmentTool" course. + * It is also supposed that there is a learning group associated with this course which contains at least + * one student and one tutor. + * <br/> + * Test case: <br/> + * - Student runs a test (Test 1) in a special "AssessmentTool" course. <br/> + * - Tutor opens the assessment tool of the same course for the specified student and checks + * whether he see the correct score. Tutor changes the score. <br/> + * - Student should see the correct score in course run as in "Evidence of achievement". <br/> + * Details: <br/> + * Test the doInSync update of the EfficiencyStatement for the STUDENT for the "AssessmentTool" course. + * <br/> + * Setup: STUDENT runs a test "Test 1", score (2) is stored. + * <br/> + * If useCodepoints is false: STUDENT stores score (1) and tutor score (7), in this order; + * else if useCodepoints is true: TUTOR stores score (7) and STUDENT stores score (1), in this order. + * + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentWithCodepointsTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + protected Selenium selenium_A; //student on node 1 + protected Selenium selenium_B; //tutor on node 2 + protected Selenium selenium_D; //student on node 1 + + private CodepointClient codepointClient_A; + private CodepointClient codepointClient_B; + + private final String COURSE_NAME = "AssessmentTool_codepoints"+System.currentTimeMillis(); + private final String GROUP_NAME = "Gruppe 1"; + + //test actors + private String STUDENT; //student username + private String TUTOR; // tutor username + + public void setUp() throws Exception { + System.out.println("AssessmentWithCodepointsTest - setUp - STARTED"); + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + TUTOR = context.getStandardAuthorOlatLoginInfos(2).getUsername(); + STUDENT = context.getStandardStudentOlatLoginInfos(1).getUsername(); + + //deleteEvidencesOfAchievement for this student + WorkflowHelper.deleteEvidencesOfAchievement("AssessmentTool_codepoints", context.getStandardStudentOlatLoginInfos(1)); + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds tutor as owner of the "AssessmentTool" + WorkflowHelper.addOwnerToLearningResource(TUTOR, COURSE_NAME); + + //"administrator" adds tutor to GROUP_NAME + WorkflowHelper.addTutorToGroup(TUTOR, COURSE_NAME, GROUP_NAME); + + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + selenium_D = context.createSeleniumAndLogin(context.getStandardStudentOlatLoginInfos(1)); + WorkflowHelper.openCourseAfterLogin(selenium_D, COURSE_NAME); + enrollInGroupAfterLogin(selenium_D, COURSE_NAME, GROUP_NAME); + + System.out.println("AssessmentWithCodepointsTest - setUp - ENDED"); + } + + /** + * STUDENT enrolls - login and enroll if not already member in groupName + * @param selenium_ + * @param courseName + * @param groupName + */ + private void enrollInGroupAfterLogin(Selenium selenium_, String courseName, String groupName) { + WorkflowHelper.openCourseAfterLogin(selenium_, courseName); + selenium_.click("ui=course::menu_courseNode(titleOfNode=Enrolment)"); + selenium_.waitForPageToLoad("30000"); + boolean alreadyEnrolled = seleniumEquals("enrolled", selenium_.getText("ui=course::content_enrollment_enrolledOrNot(nameOfGroup=" + groupName + ")")); + if(!alreadyEnrolled) { + selenium_.click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=" + groupName + ")"); + selenium_.waitForPageToLoad("30000"); + assertTrue(selenium_.isTextPresent("You have already enroled for the learning group mentioned below")); + } + selenium_.click("ui=tabs::logOut()"); + selenium_.waitForPageToLoad("30000"); + } + + + /** + * Tests assessment tool. + * Student runs a test (Test 1) in a special "AssessmentTool" course. + * Tutor opens the assessment tool of the same course for the specified student and checks + * whether he see the correct score. Tutor changes the score. + * Student should see the correct score in course run as in "Evidence of achievement" + * + * @throws Exception + */ + public void testEfficiencyStatementUpdate() throws Exception { + System.out.println("AssessmentWithCodepointsTest - testEfficiencyStatementUpdate - STARTED"); + + //uses codepoints to test the efficiencyStatement update + boolean useCodepoints = true; + doTestEfficiencyStatementUpdateWithCodepoints(useCodepoints); + + System.out.println("AssessmentWithCodepointsTest - testEfficiencyStatementUpdate - ENDED"); + } + + + /** + * Test the doInSync update of the EfficiencyStatement for the STUDENT for the "AssessmentTool" course. + * Uses Codepoints. + * <p> + * Setup: STUDENT runs a test "Test 1", score (2) is stored. + * <p> + * If useCodepoints is false: STUDENT stores score (1) and tutor score (7), in this order. + * else if useCodepoints is true: TUTOR stores score (7) and STUDENT stores score (1), in this order + * + * @param useCodepoints + * @throws Exception + */ + private void doTestEfficiencyStatementUpdateWithCodepoints(boolean useCodepoints) throws Exception { + System.out.println("AssessmentWithCodepointsTest - doTestEfficiencyStatementUpdateWithCodepoints - STARTED - useCodepoints: " + useCodepoints); + Context context = Context.getContext(); + selenium_A = context.createSeleniumAndLogin(context.getStandardStudentOlatLoginInfos(1)); + + WorkflowHelper.openCourseAfterLogin(selenium_A, COURSE_NAME); + //setup: student runs the test first time ("Test 1" and gets a score equals with 2) + selenium_A.click("ui=course::menu_courseNode(titleOfNode=Struktur 1)"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=course::menu_courseNode(titleOfNode=Test 1)"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=commons::start()"); + selenium_A.waitForPageToLoad("30000"); + //select item, choose answer and submit answer + selenium_A.click("ui=qti::menuItem(titleOfItem=Single Choice)"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=qti::testItemFormElement(text=Antwort 3)"); + selenium_A.click("ui=qti::saveAnswer()"); + selenium_A.waitForPageToLoad("30000"); + //select item, choose answer and submit answer + selenium_A.click("ui=qti::menuItem(titleOfItem=Multiple Choice)"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=qti::testItemFormElement(text=Antwort 2)"); + selenium_A.click("ui=qti::testItemFormElement(text=Antwort 3)"); + selenium_A.click("ui=qti::saveAnswer()"); + selenium_A.waitForPageToLoad("30000"); + //submit test + selenium_A.click("ui=qti::finishTest()"); + selenium_A.waitForPageToLoad("30000"); + boolean confirmedSubmit = selenium_A.getConfirmation().matches("^Do you really want to submit[\\s\\S]$"); + + assertTrue(confirmedSubmit); + + + assertEquals("2", selenium_A.getText("ui=qti::achievedScore()")); + selenium_A.click("ui=qti::closeTest()"); //updateEfficiencyStatement(3) + selenium_A.waitForPageToLoad("30000"); + assertEquals("2.000", selenium_A.getText("ui=qti::yourScore()")); + //end setup - student achieved a score of 2.000 + + codepointClient_A = Context.getContext().createCodepointClient(1); + CodepointRef beforeSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.assessment.NewCachePersistingAssessmentManager.beforeSyncUpdateUserEfficiencyStatement"); + beforeSyncCp_A.setHitCount(0); + if(useCodepoints) + beforeSyncCp_A.enableBreakpoint(); + + CodepointRef doInSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.assessment.NewCachePersistingAssessmentManager.doInSyncUpdateUserEfficiencyStatement"); + doInSyncCp_A.setHitCount(0); + if(useCodepoints) + doInSyncCp_A.enableBreakpoint(); + + codepointClient_B = Context.getContext().createCodepointClient(2); + CodepointRef doInSyncCp_B = codepointClient_B.getCodepoint("org.olat.course.assessment.NewCachePersistingAssessmentManager.doInSyncUpdateUserEfficiencyStatement"); + doInSyncCp_B.setHitCount(0); + if(useCodepoints) + doInSyncCp_B.enableBreakpoint(); + + CodepointRef afterSyncCp_B = codepointClient_B.getCodepoint("org.olat.course.assessment.NewCachePersistingAssessmentManager.afterSyncUpdateUserEfficiencyStatement"); + afterSyncCp_B.setHitCount(0); + if(useCodepoints) + afterSyncCp_B.enableBreakpoint(); + + selenium_B = context.createSeleniumAndLogin(context.getStandardAuthorOlatLoginInfos(2)); + WorkflowHelper.openCourseAfterLogin(selenium_B, COURSE_NAME); + + //STUDENT runs the "Test 1" and gets a score equals with 1. + selenium_A.click("ui=commons::start()"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=qti::menuItem(titleOfItem=Single Choice)"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=qti::testItemFormElement(text=Antwort 3)"); + selenium_A.click("ui=qti::saveAnswer()"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=qti::finishTest()"); + assertTrue(selenium_A.getConfirmation().matches("^Do you really want to submit[\\s\\S]$")); + + //A: check if codepoint reached: beforeSyncCp_A + if(useCodepoints) { + beforeSyncCp_A.assertBreakpointReached(1, 20000); + System.out.println("beforeSyncCp_A.assertBreakpointReached"); + } + + //tutor opens the assessment tool of the same course and overwrites the score of "Test 1" with the value 7 + selenium_B.click("ui=course::toolbox_courseTools_assessmentTool()"); + selenium_B.waitForPageToLoad("30000"); + selenium_B.click("ui=course::assessment_selectType(text=As per user)"); + selenium_B.waitForPageToLoad("30000"); + selenium_B.click("ui=course::assessment_selectUser(username=" + STUDENT + ")"); + selenium_B.waitForPageToLoad("10000"); + if(useCodepoints) { + //student last score was not stored yet + assertEquals("2.000", selenium_B.getText("ui=course::assessment_scoreInTable(title=Test 1)")); + } else { + assertEquals("1.000", selenium_B.getText("ui=course::assessment_scoreInTable(title=Test 1)")); + } + //tutor selects "Test 1" and change its score and passed info + selenium_B.click("ui=course::assessment_selectAssessmentCourseNode(title=Test 1)"); + selenium_B.waitForPageToLoad("30000"); + selenium_B.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Score)", "7"); + selenium_B.click("ui=course::assessment_setPassedYes()"); + selenium_B.click("ui=commons::save()"); //updateEfficiencyStatement(2) + // B: check if codepoint reached: doInSyncCp_B, and continue A thread + //this means that tutor's score is first stored and will be overwritten by the students's score + if(useCodepoints) { + doInSyncCp_B.assertBreakpointReached(1, 20000); + System.out.println("doInSyncCp_B.assertBreakpointReached"); + TemporaryPausedThread[] threadsA = beforeSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + System.out.println("beforeSyncCp_A continue threads"); + + //B: continue thread + doInSyncCp_A.assertBreakpointNotReached(20000); + System.out.println("doInSyncCp_A.assertBreakpointNotReached"); + TemporaryPausedThread[] threadsB = doInSyncCp_B.getPausedThreads(); + threadsB[0].continueThread(); + System.out.println("doInSyncCp_B continue threads"); + + //B: leave the doInSync block + afterSyncCp_B.assertBreakpointReached(1, 40000); + doInSyncCp_A.assertBreakpointReached(1, 40000); + threadsA = doInSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + System.out.println("doInSyncCp_A continue threads"); + threadsB = afterSyncCp_B.getPausedThreads(); + threadsB[0].continueThread(); + System.out.println("afterSyncCp_B continue threads"); + } + selenium_B.waitForPageToLoad("30000"); + //what tutor sees + /*if(useCodepoints) { + //assert score on "Struktur 1" to be the sum of the "Test 1" and "Bewertung 1" scores + assertEquals("1.000", selenium_B.getText("ui=course::assessment_scoreInTable(title=Struktur 1)")); + //assert score on "Struktur 2" to be the half of sum of the "Test 1" and "Bewertung 1" scores + assertEquals("0.500", selenium_B.getText("ui=course::assessment_scoreInTable(title=Struktur 2)")); + } else {*/ + //assert score on "Struktur 1" to be the sum of the "Test 1" and "Bewertung 1" scores + assertEquals("7.000", selenium_B.getText("ui=course::assessment_scoreInTable(title=Struktur 1)")); + //assert score on "Struktur 2" to be the half of sum of the "Test 1" and "Bewertung 1" scores + assertEquals("3.500", selenium_B.getText("ui=course::assessment_scoreInTable(title=Struktur 2)")); + //} + + //what student sees + selenium_A.waitForPageToLoad("30000"); + assertEquals("1", selenium_A.getText("ui=qti::achievedScore()")); + + selenium_A.click("ui=qti::closeTest()"); //updateEfficiencyStatement(1) + selenium_A.waitForPageToLoad("30000"); + if(useCodepoints) { + assertEquals("1.000", selenium_A.getText("ui=qti::yourScore()")); + } else { + assertEquals("7.000", selenium_A.getText("ui=qti::yourScore()")); + } + + // student checks "Evidence of achievement" in HOME - show details + selenium_A.click("ui=tabs::home()"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=home::menu_evidencesOfAchievement()"); + selenium_A.waitForPageToLoad("30000"); + selenium_A.click("ui=home::content_evidencesOfAchievement_selectDetails(title=" + COURSE_NAME + ")"); + Thread.sleep(10000); + selenium_A.selectWindow(selenium_A.getAllWindowTitles()[2]); + assertTrue(selenium_A.isTextPresent("Evidence of achievement")); + //check score in table + assertEquals("1.000", selenium_A.getText("ui=course::assessment_scoreInTable(title=Test 1)")); + + System.out.println("AssessmentWithCodepointsTest - doTestEfficiencyStatementUpdateWithCodepoints - ENDED"); + } + + + @Override + public void cleanUpAfterRun() { + System.out.println("AssessmentWithCodepointsTest - cleanUpAfterRun - STARTED"); + //resetScoreCalculationRule(); + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + System.out.println("AssessmentWithCodepointsTest - cleanUpAfterRun - ENDED"); + } + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/ClusteredCourseExportTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/ClusteredCourseExportTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b2ab07acdc403b4c140d0d593fa76d9e18218810 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/ClusteredCourseExportTest.java @@ -0,0 +1,184 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + + /** + * Tests that no course export, copy and edit could occur concurrently - clusterwide - + * but protected by a GUI lock. + * <br/> + * Test setup: <br/> + * - admin clones DEMO_COURSE_NAME and adds author as owner to this. <br/> + * - admin and author login on separate nodes + * (Theoretically, since this depends of the multiVmOlatUrl1 and multiVmOlatUrl2 in customcontext.xml) + * <br/> + * Test case: <br/> + * - author opens "Demo Course" and start editing course <br/> + * - administrator wants to export course - but it is locked <br/> + * - author closes course editor <br/> + * - administrator exports course - threadA stops at codepoint - <br/> + * - author want to open course editor but course locked for export - threadA stopped at codepoint - <br/> + * - continue threadA - exports finishes - lock released <br/> + * - author opens successfully course editor <br/> + * - logout + * + * @author Lavinia Dumitrescu + * + */ +public class ClusteredCourseExportTest extends BaseSeleneseTestCase { + + private OLATWorkflowHelper workflow_A; //administrator on node 1 + private OLATWorkflowHelper workflow_B; //author on node 2 + private CodepointClient codepointClient_A; + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "ClusteredCourseExportTest" + System.currentTimeMillis(); + + /** + * "administrator" adds author as owner of the "Demo Course" + */ + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //clone DEMO_COURSE_NAME and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + //"administrator" adds author as owner of the "Demo Course" + String authorUsername = Context.getContext().getStandardAuthorOlatLoginInfos(1).getUsername(); + WorkflowHelper.addOwnerToLearningResource(authorUsername, COURSE_NAME); + + workflow_A = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflow_B = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + } + + /** + * Tests that no course export, copy and edit could occur concurently - clusterwide - + * but protected by a GUI lock. + * Steps: + * - author opens "Demo Course" and start editing course + * - administrator wants to export course - but it is locked + * - author closes course editor + * - administrator exports course - threadA stops at codepoint - + * - author want to open course editor but course locked for export - threadA stopped at codepoint - + * - continue threadA - exports finishes - lock released + * - author opens successfully course editor + * - logout + * + * @throws Exception + */ + public void testExportCourse() throws Exception { + + Context context = Context.getContext(); + codepointClient_A = context.createCodepointClient(1); + CodepointRef longExportStartedCp_A = codepointClient_A.getCodepoint("org.olat.course.CourseFactory.longExportCourseToZIP"); + longExportStartedCp_A.setHitCount(0); + longExportStartedCp_A.enableBreakpoint(); + + //author opens "Demo Course" + CourseEditor courseEditor_B = workflow_B.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + + //administrator wants to export course - but it is locked + LRDetailedView lRDetailedView_A = workflow_A.getLearningResources().searchResource(COURSE_NAME, null); + Selenium selenium_A = lRDetailedView_A.getSelenium(); + selenium_A.click("ui=learningResources::toolbox_learningResource_exportContent()"); + //no need for waitForPageToLoad since the message shows up immediately for a very short time + + SeleniumHelper.waitUntilTextPresent(selenium_A, "This course is currently locked", 20); + + //author closes course editor and releases lock + CourseRun courseRun_B = courseEditor_B.closeToCourseRun(); + + //administrator exports course + selenium_A.click("ui=learningResources::toolbox_learningResource_exportContent()"); + //pause at breakpoint + longExportStartedCp_A.assertBreakpointReached(1, 20000); + + //author tries to reopen course editor and gets "already locked" warning + Selenium selenium_B = courseRun_B.getSelenium(); + selenium_B.click("ui=course::toolbox_courseTools_courseEditor()"); + //no need for waitForPageToLoad since the message shows up immediately for a very short time + for (int second = 0;; second++) { + if (second >= 120) fail("timeout"); //WARNING: HERE POTENTIAL FAILURE EACH TIME THE TRANSLATION CHANGES! + try { + //Make sure that the string really exists in the _en property file + if (selenium_B.isTextPresent("This course is being locked by") || + selenium_B.isTextPresent("This course is being edited by")) break; + } catch (Exception e) {} + Thread.sleep(1000); + } + + //continue threads + TemporaryPausedThread[] threadsA = longExportStartedCp_A.getPausedThreads(); + threadsA[0].continueThread(); + //Thread.sleep(1000); + Thread.sleep(3000); + + //author opens successfully the course editor + selenium_B.click("ui=course::toolbox_courseTools_courseEditor()"); + boolean isLockedByEncountered = false; + boolean isEditedByEncountered = false; + for (int second = 0;; second++) { + if (selenium_B.isTextPresent("This course was last published on")) break; + if (second >= 120) { + if (isLockedByEncountered) { + fail("Timeout. But encountered String 'This course is currently locked by'. Maybe that's the actual problem?"); + } + if (isEditedByEncountered) { + fail("Timeout. But encountered String 'This course is currently edited by'. Maybe that's the actual problem?"); + } + fail("Timeout"); + } + try { + //Make sure that the string really exists in the _en property file + if (selenium_B.isTextPresent("This course was last published on")) break; + if (selenium_B.isTextPresent("This course is currently locked by")) { + System.out.println("Encountered String 'This course is currently locked by'!!!!!"); + isLockedByEncountered = true; + } + if (selenium_B.isTextPresent("This course is currently edited by")) { + System.out.println("Encountered String 'This course is currently edited by'!!!!!"); + isEditedByEncountered = true; + } + } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium_A.click("ui=tabs::logOut()"); + selenium_B.click("ui=tabs::logOut()"); + } + + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/ConcurrentEnrolmentWithCheckpointsTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/ConcurrentEnrolmentWithCheckpointsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ab1736cb5984181e30d641676dbd2295f2c3ab2b --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/ConcurrentEnrolmentWithCheckpointsTest.java @@ -0,0 +1,206 @@ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + +/** + * Tests concurrent Enrollment with codepoints. + * + * Test case: <br/> + * 5 users try to subscribe to group with just one place, only one should get into group. + * <br/> + * Make sure that the rest get appropriate error messages. + * + * + * + */ +public class ConcurrentEnrolmentWithCheckpointsTest extends BaseSeleneseTestCase { + + + private CodepointClient codepointClient_1; + private CodepointClient codepointClient_2; + + protected Selenium seleniums[] = new Selenium[5]; + + private final static String COURSE_NAME = "Course_for_Enrolment_Concurrency" + System.currentTimeMillis(); + + + public void testConcurrentEnrolmentWithCodepointsTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(2, "enrolstudi02", standardPassword, true, false, false, false, false); + OlatLoginInfos student03= context.createuserIfNotExists(1, "enrolstudi03", standardPassword, true, false, false, false, false); + OlatLoginInfos student04= context.createuserIfNotExists(2, "enrolstudi04", standardPassword, true, false, false, false, false); + OlatLoginInfos student05= context.createuserIfNotExists(1, "enrolstudi05", standardPassword, true, false, false, false, false); + + { + // Author01 creates course with learning group (max 1 participant) and enrolment course element + OLATWorkflowHelper olatWorkflow_0 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + System.out.println("logging in browser 1..."); + LearningResources learningResources = olatWorkflow_0.getLearningResources(); + learningResources.createResource(COURSE_NAME, "Enrolment Test", LearningResources.LR_Types.COURSE); + CourseRun courseRun = learningResources.searchAndShowMyCourseContent(COURSE_NAME); + GroupManagement groupManagement = courseRun.getGroupManagement(); + groupManagement.createLearningGroup("learning group selenium 5", "fifth lg", 1, false, false); + courseRun = groupManagement.close(); + CourseEditor courseEditor = courseRun.getCourseEditor(); + EnrolmentEditor enrolmentEditor = (EnrolmentEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.ENROLMENT, true, null); + enrolmentEditor.selectLearningGroups("learning group selenium 5"); + courseEditor.publishCourse(); + courseEditor.closeToCourseRun(); + olatWorkflow_0.logout(); + } + + //node 1 + codepointClient_1 = Context.getContext().createCodepointClient(1); + CodepointRef doInSync1Cp_1 = codepointClient_1.getCodepoint("org.olat.course.nodes.en.EnrollmentManager.doInSync1"); + doInSync1Cp_1.setHitCount(0); + doInSync1Cp_1.enableBreakpoint(); + + CodepointRef doInSync2Cp_1 = codepointClient_1.getCodepoint("org.olat.course.nodes.en.EnrollmentManager.doInSync2"); + doInSync2Cp_1.setHitCount(0); + doInSync2Cp_1.enableBreakpoint(); + + CodepointRef afterDoInSyncCp_1 = codepointClient_1.getCodepoint("org.olat.course.nodes.en.EnrollmentManager.afterDoInSync"); + afterDoInSyncCp_1.setHitCount(0); + afterDoInSyncCp_1.enableBreakpoint(); + + //node 2 + codepointClient_2 = Context.getContext().createCodepointClient(2); + CodepointRef doInSyncCp_2 = codepointClient_2.getCodepoint("org.olat.course.nodes.en.EnrollmentManager.doInSync1"); + doInSyncCp_2.setHitCount(0); + doInSyncCp_2.enableBreakpoint(); + + { + // student01 opens course and navigates to enrolment course element + OLATWorkflowHelper olatWorkflow_0 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + CourseRun courseRun = olatWorkflow_0.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + seleniums[0] = enrolmentRun.getSelenium(); + } + + { + // student02 opens course and navigates to enrolment course element + System.out.println("logging in browser 2..."); + OLATWorkflowHelper olatWorkflow_1 = context.getOLATWorkflowHelper(student02); + CourseRun courseRun = olatWorkflow_1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + seleniums[1] = enrolmentRun.getSelenium(); + } + + { + // student03 opens course and navigates to enrolment course element + System.out.println("logging in browser 3..."); + OLATWorkflowHelper olatWorkflow_2 = context.getOLATWorkflowHelper(student03); + CourseRun courseRun = olatWorkflow_2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + seleniums[2] = enrolmentRun.getSelenium(); + } + + { + // student04 opens course and navigates to enrolment course element + System.out.println("logging in browser 4..."); + OLATWorkflowHelper olatWorkflow_3 = context.getOLATWorkflowHelper(student04); + CourseRun courseRun = olatWorkflow_3.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + seleniums[3] = enrolmentRun.getSelenium(); + } + + { + // student05 opens course and navigates to enrolment course element + System.out.println("logging in browser 5..."); + OLATWorkflowHelper olatWorkflow_4 = context.getOLATWorkflowHelper(student05); + CourseRun courseRun = olatWorkflow_4.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + seleniums[4] = enrolmentRun.getSelenium(); + } + + // All students enrol, only student01 should get into group + { + seleniums[0].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[1].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + + doInSync1Cp_1.assertBreakpointReached(1, 20000); + System.out.println("doInSync1Cp_1.assertBreakpointReached"); + + doInSyncCp_2.assertBreakpointNotReached(20000); + System.out.println("doInSyncCp_2.assertBreakpointNotReached"); + + TemporaryPausedThread[] threads1 = doInSync1Cp_1.getPausedThreads(); + threads1[0].continueThread(); + System.out.println("doInSync1Cp_1 continue threads"); + doInSync1Cp_1.disableBreakpoint(true); + + doInSync2Cp_1.assertBreakpointReached(1, 20000); + System.out.println("doInSync2Cp_1.assertBreakpointReached"); + + doInSyncCp_2.assertBreakpointNotReached(20000); + System.out.println("doInSyncCp_2.assertBreakpointNotReached"); + + threads1 = doInSync2Cp_1.getPausedThreads(); + threads1[0].continueThread(); + System.out.println("doInSync2Cp_1 continue threads"); + doInSync2Cp_1.disableBreakpoint(true); + + + afterDoInSyncCp_1.assertBreakpointReached(1, 20000); + System.out.println("afterDoInSyncCp_1.assertBreakpointReached"); + + doInSyncCp_2.assertBreakpointReached(1, 20000); + System.out.println("doInSyncCp_2.assertBreakpointReached"); + TemporaryPausedThread[] threads2 = doInSyncCp_2.getPausedThreads(); + threads2[0].continueThread(); + System.out.println("doInSyncCp_2 continue threads"); + doInSyncCp_2.disableBreakpoint(true); + + threads1 = afterDoInSyncCp_1.getPausedThreads(); + threads1[0].continueThread(); + System.out.println("afterDoInSyncCp_1 continue threads"); + afterDoInSyncCp_1.disableBreakpoint(true); + + seleniums[2].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[3].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[4].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + + + int numWinners = 0; + int numLoosers = 0; + for(int i=0; i<5; i++) { + seleniums[i].waitForPageToLoad("30000"); + if (seleniums[i].isTextPresent("enrolled")) { + numWinners++; + } else if (seleniums[i].isTextPresent("In the meantime this group is complete. Please select another one.")) { + numLoosers++; + } else { + fail("oups..."); + } + } + assertEquals("expected only 1 winner", 1, numWinners); + assertEquals("expected only 4 loosers", 4, numLoosers); + //assertEquals("expected only 1 loosers", 1, numLoosers); + + } + { + //author01 deletes course + /*OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LRDetailedView lRDetailedView = workflow.getLearningResources().searchMyResource(COURSE_NAME); + lRDetailedView.deleteLR();*/ + } + } +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/CopyCourseTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/CopyCourseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..46fcd14c40be1245cdf6d13493bb239ee176f6c0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/CopyCourseTest.java @@ -0,0 +1,174 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; + +import com.thoughtworks.selenium.Selenium; + +/** + * Tests CourseFactory.copyCourse() in cluster mode - with codepoints. <br/> + * + * Test setup: <br/> + * administrator adds author as owner of the "Demo Course". <br/> + * + * Test case: <br/> + * Creates 2 copies ("COPY A - DEMO COURSE" and "COPY B - DEMO COURSE") of the same "Demo Course". <br/> + * Administrator and author create 2 copy of the same course simultaneously, so if the administrator starts + * to copy and the thread_A pauses at codepoint, the author finds the course locked when tries to copy. + * Author succeds to copy after the thread_A is continued. + * <br/> + * + * 13.09.2010: + * fixed to conform with the new code behaviour (a course copy is already created after click copyLR, + * before insert new title/description and OK). + * + * @author Lavinia Dumitrescu + * + */ +public class CopyCourseTest extends BaseSeleneseTestCase { + + protected Selenium selenium_B; + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "CopyCourse" + System.currentTimeMillis(); + + private CodepointClient codepointClient_A; + + + public void setUp() throws Exception { + System.out.println("CopyCourseTest - setUp - START"); + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //clone "Demo Course" and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + //author + OlatLoginInfos authorOlatLoginInfos = context.getStandardAuthorOlatLoginInfos(1); + //"administrator" adds author as owner of the "Demo Course" + WorkflowHelper.addOwnerToLearningResource(authorOlatLoginInfos.getUsername(), COURSE_NAME); + System.out.println("CopyCourseTest - setUp - END"); + } + + + public void testCopyCourse() throws Exception { + Context context = Context.getContext(); + + //administrator + OLATWorkflowHelper workflow1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + LRDetailedView lRDetailedView1 = workflow1.getLearningResources().searchResource(COURSE_NAME, null); + + //author - owner of the "Demo Course" + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LRDetailedView lRDetailedView2 = workflow2.getLearningResources().searchResource(COURSE_NAME,null); + + codepointClient_A = context.createCodepointClient(1); + CodepointRef longCopyStartedCp_A = codepointClient_A.getCodepoint("org.olat.course.CourseFactory.copyCourseAfterSaveTreeModel"); + longCopyStartedCp_A.setHitCount(0); + longCopyStartedCp_A.enableBreakpoint(); + + //lRDetailedView1.copyLR("COPY A - DEMO COURSE", "bla"); + this.startCopyLR(lRDetailedView1.getSelenium()); + + //A: check if codepoint reached: longCopyStartedCp_A + longCopyStartedCp_A.assertBreakpointReached(1, 20000); + System.out.println("longCopyStartedCp_A.assertBreakpointReached"); + + selenium_B = lRDetailedView2.getSelenium(); + selenium_B.click("ui=learningResources::toolbox_learningResource_copy()"); + selenium_B.waitForPageToLoad("30000"); + //course still locked + for (int second = 0;; second++) { + if (second >= 120) fail("timeout"); + try { + //Make sure that the string really exists in the _en property file + if (selenium_B.isTextPresent("This course is currently locked by") || + selenium_B.isTextPresent("This course is currently edited by")) break; + } catch (Exception e) {} + Thread.sleep(1000); + } + //A: continue threads hold by longCopyStartedCp_A + TemporaryPausedThread[] threadsA = longCopyStartedCp_A.getPausedThreads(); + threadsA[0].continueThread(); + longCopyStartedCp_A.disableBreakpoint(true); + Thread.sleep(3000); + this.finishCopyLR(lRDetailedView1.getSelenium(), "COPY A - DEMO COURSE", "bla"); + + Thread.sleep(5000); + lRDetailedView2.copyLR("COPY B - DEMO COURSE", null); + + workflow1.logout(); + workflow2.logout(); + } + + /** + * + * @param selenium + */ + private void startCopyLR(Selenium selenium) { + if(selenium.isElementPresent("ui=learningResources::toolbox_learningResource_copy()")) { + selenium.click("ui=learningResources::toolbox_learningResource_copy()"); + + } else { + throw new IllegalStateException("Cannot copy learning resource!"); + } + } + + /** + * + * @param selenium + * @param newTitle + * @param newDescription + */ + private void finishCopyLR(Selenium selenium, String newTitle, String newDescription) { + selenium.type("ui=learningResources::dialog_title()", newTitle); + if(newDescription!=null) { + selenium.type("ui=learningResources::dialog_description()", newDescription); + } + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + } + + + /** + * Deletes the created copies. + */ + @Override + public void cleanUpAfterRun() { + System.out.println("CopyCourseTest - cleanUpAfterRun - START"); + Context context = Context.getContext(); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflow.getLearningResources().searchResource("COPY A - DEMO COURSE", null).deleteLR(); + workflow.getLearningResources().searchResource("COPY B - DEMO COURSE", null).deleteLR(); + System.out.println("CopyCourseTest - cleanUpAfterRun - END"); + } +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/CourseEditingTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/CourseEditingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d75315c41b8c1f60581de8b36b8e79d1da009603 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/CourseEditingTest.java @@ -0,0 +1,171 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + + /** + * Tests course editing in clustered mode, and that the GUI locking works, + * that is a course could be edited by only a single user at a time. + * <br/> + * Test setup: <br/> + * Needs a clean "Demo Course".</br> + * + * Test case: <br/> + * The cluster_B node should be able the see the latest inserted node by cluster_A node after the course lock release. </br> + * - cluster_A: inserts a Structure course element, assertBreakpointReached </br> + * - cluster_B: try to open the course editor of the same course but gets a "course locked" warning </br> + * - cluster_A: continues the thread </br> + * - cluster_A: closes course editor </br> + * - cluster_B: opens editor, selects the first Structure node, changes the title, closes the editor </br> + * + * @author Lavinia Dumitrescu + * + */ +public class CourseEditingTest extends BaseSeleneseTestCase { + + protected Selenium selenium_A; + protected Selenium selenium_B; + private CodepointClient codepointClient_A; + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "CourseEditing" + System.currentTimeMillis(); + + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //clone DEMO_COURSE_NAME and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + //author + OlatLoginInfos authorOlatLoginInfos = context.getStandardAuthorOlatLoginInfos(2); + //"administrator" adds author as owner of the "Demo Course" + WorkflowHelper.addOwnerToLearningResource(authorOlatLoginInfos.getUsername(), COURSE_NAME); + selenium_B = context.createSeleniumAndLogin(context.getStandardAuthorOlatLoginInfos(2)); + + //administrator + selenium_A = context.createSeleniumAndLogin(context.getStandardAdminOlatLoginInfos(1)); + } + + /** + * Needs a clean "Demo Course".</br> + * Tests course editing in clustered mode. + * The cluster_B node should be able the see the latest inserted node by cluster_A node after the course lock release. </br> + * - cluster_A: inserts a Structure course element, assertBreakpointReached </br> + * - cluster_B: try to open the course editor of the same course but gets a "course locked" warning </br> + * - cluster_A: continues the thread </br> + * - cluster_A: closes course editor </br> + * - cluster_B: opens editor, selects the first Structure node, changes the title, closes the editor </br> + * @throws Exception + */ + public void testCourseEditing() throws Exception { + + WorkflowHelper.openCourseAfterLogin(selenium_A, COURSE_NAME); + WorkflowHelper.openCourseAfterLogin(selenium_B, COURSE_NAME); + + Context context = Context.getContext(); + //codepoints node A + codepointClient_A = context.createCodepointClient(1); + CodepointRef startInsertCp_A = codepointClient_A.getCodepoint("org.olat.course.editor.EditorMainController.startInsertNode"); + startInsertCp_A.setHitCount(0); + startInsertCp_A.enableBreakpoint(); + + selenium_A.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium_A.waitForPageToLoad("30000"); + + //A: inserts Structure course node + selenium_A.click("ui=courseEditor::toolbox_insertCourseElements_insertStructure()"); + + //A: check if codepoint reached: startInsertCp_A + startInsertCp_A.assertBreakpointReached(1, 20000); + System.out.println("startInsertCp_A.assertBreakpointReached"); + + + //B: start course editor in cluster_B - this should lead to a courseLocked warning + selenium_B.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium_B.waitForPageToLoad("30000"); + + //B: check if "course locked" warning shows up - + //selenium_B.click("ui=dialog::OK()"); //we don't really have the chance to click OK on the warning dialog + //selenium_B.waitForPageToLoad("30000"); + /*for (int second = 0;; second++) { //TODO: ld: for some reason this check doesn't work + if (second >= 120) fail("timeout"); + try { + if (selenium_B.isTextPresent("This course is currently edited by")) break; + } catch (Exception e) {} + Thread.sleep(1000); + }*/ + //WORKAROUND for the "course locked" check: try again to open course editor + selenium_B.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium_B.waitForPageToLoad("30000"); + + //A: continue threads hold by startInsertCp_A + TemporaryPausedThread[] threadsA = startInsertCp_A.getPausedThreads(); + threadsA[0].continueThread(); + + selenium_A.waitForPageToLoad("10000"); + //no need for clickAndWait here + selenium_A.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + + selenium_A.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium_A.waitForPageToLoad("30000"); + + selenium_A.click("ui=courseEditor::toolbox_editorTools_closeEditor()"); + selenium_A.waitForPageToLoad("30000"); + + //A: add CodepointRef here in cluster_A: endCourseEditCp_A + + //B: start course editor in cluster_B + selenium_B.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium_B.waitForPageToLoad("30000"); + + //B: select the (Structure) node inserted by A + selenium_B.click("ui=course::menu_structureNode()"); + selenium_B.waitForPageToLoad("30000"); + //B: change node title + selenium_B.type("ui=courseEditor::content_TitleDescription_shortTitle()", "Structure B"); + selenium_B.click("ui=commons::save()"); + selenium_B.waitForPageToLoad("30000"); + + + //B: close course editor (releases lock) + selenium_B.click("ui=courseEditor::toolbox_editorTools_closeEditor()"); + selenium_B.waitForPageToLoad("30000"); + + //A: continue threads hold by endCourseEditCp_A + + selenium_A.click("ui=tabs::logOut()"); + selenium_B.click("ui=tabs::logOut()"); + + } + + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/CourseGroupChatClusterTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/CourseGroupChatClusterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6514a1b4887fdc77b0a71d214ab06e10509a74c5 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/CourseGroupChatClusterTest.java @@ -0,0 +1,151 @@ +package org.olat.test.functional.codepoints.cluster; + +import org.junit.Ignore; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + +/** + * test groupChat stuff and polling (changing interval) + * + * @author Guido + * + */ +@Ignore +public class CourseGroupChatClusterTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = Context.DEMO_COURSE_NAME_1; + + protected Selenium selenium_1; + protected Selenium selenium_2; + private CodepointClient codepointClient_A, codepointClient_B; + + + public void testCourseChat() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OLATWorkflowHelper workflow_1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + OLATWorkflowHelper workflow_2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + + CourseRun curseRun1 = workflow_1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + selenium_1 = curseRun1.getSelenium(); + + CourseRun curseRun2 = workflow_2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + selenium_2 = curseRun2.getSelenium(); + + codepointClient_A = context.createCodepointClient(1); + CodepointRef beforeSyncA = codepointClient_A.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-before-sync.org.olat.instantMessaging.groupchat.GroupChatJoinTask.run"); + beforeSyncA.setHitCount(0); + beforeSyncA.enableBreakpoint(); + + codepointClient_B = context.createCodepointClient(2); + CodepointRef beforeSyncB = codepointClient_B.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-before-sync.org.olat.instantMessaging.groupchat.GroupChatJoinTask.run"); + beforeSyncB.setHitCount(0); + beforeSyncB.enableBreakpoint(); + + CodepointRef inSyncA = codepointClient_A.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-in-sync.org.olat.instantMessaging.groupchat.GroupChatJoinTask.run"); + inSyncA.setHitCount(0); + + CodepointRef inSyncB = codepointClient_B.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-in-sync.org.olat.instantMessaging.groupchat.GroupChatJoinTask.run"); + inSyncB.setHitCount(0); + + selenium_1.mouseMoveAt("ui=courseChat::openCourseChat()", "300,300"); + selenium_1.click("ui=courseChat::openCourseChat()"); + + selenium_2.mouseMoveAt("ui=courseChat::openCourseChat()", "300,300"); + selenium_2.click("ui=courseChat::openCourseChat()"); + + //both node are waiting to entry sync block + Thread.sleep(2000); + inSyncB.assertHitCount(0); + inSyncA.assertHitCount(0); + + beforeSyncA.assertHitCount(1); + beforeSyncB.assertHitCount(1); + + TemporaryPausedThread[] threadsA = beforeSyncB.getPausedThreads(); + assertNotNull(threadsA); + assertEquals(1, threadsA.length); + + TemporaryPausedThread[] threadsB = beforeSyncA.getPausedThreads(); + assertNotNull(threadsB); + assertEquals(1, threadsB.length); + + // continue the first + threadsA[0].continueThread(); + Thread.sleep(1500); + + // continue the second + threadsB[0].continueThread(); + Thread.sleep(500); + + + Thread.sleep(16000);//wait until course chat link is save (no reload warning) + + + //open course chat + /*selenium_1.mouseMoveAt("ui=courseChat::openCourseChat()", "300,300"); + selenium_1.click("ui=courseChat::openCourseChat()");*/ + selenium_1.waitForPageToLoad("30000"); + Thread.sleep(1000); + + if(!selenium_1.isElementPresent("ui=courseChat::withinCourseChat()")) { + Thread.sleep(5000); + } + selenium_1.click("ui=courseChat::withinCourseChat()"); + selenium_1.waitForPageToLoad("30000"); + + selenium_1.click("ui=courseChat::toggleAnonymous()"); + selenium_1.waitForPageToLoad("30000"); + + Thread.sleep(16000); + + //open course chat + /*selenium_2.mouseMoveAt("ui=courseChat::openCourseChat()", "300,300"); + selenium_2.click("ui=courseChat::openCourseChat()");*/ + selenium_2.waitForPageToLoad("30000"); + Thread.sleep(3000); + + if(!selenium_2.isElementPresent("ui=courseChat::withinCourseChat()")) { + Thread.sleep(5000); + } + selenium_2.click("ui=courseChat::withinCourseChat()"); + selenium_2.waitForPageToLoad("30000"); + selenium_2.click("ui=courseChat::toggleAnonymous()"); + selenium_2.waitForPageToLoad("30000"); + + //if both name changed polling works and chat window is working + Thread.sleep(3000); + if (!selenium_1.isTextPresent("("+context.getStandardAdminOlatLoginInfos(1).getUsername()+")")) { + Thread.sleep(6000); //wait for another 6s + } + assertTrue(selenium_1.isTextPresent("("+context.getStandardAdminOlatLoginInfos(1).getUsername()+")")); + + if (!selenium_2.isTextPresent("("+context.getStandardAuthorOlatLoginInfos(2).getUsername()+")")) { + Thread.sleep(6000); //wait for another 6s + } + assertTrue(selenium_2.isTextPresent("("+context.getStandardAuthorOlatLoginInfos(2).getUsername()+")")); + + + //send msg and check on second node if it arrived + String msg = Long.valueOf(System.currentTimeMillis()).toString(); + selenium_1.type("ui=courseChat::sendMsgInputField()", msg); + selenium_1.click("ui=courseChat::sendMsgButton()"); + selenium_1.waitForPageToLoad("30000"); + Thread.sleep(3000); //after 3s it should be there + assertTrue(selenium_2.isTextPresent(msg)); + + + + + + } + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterDeleteProjectGroupTstDISABLED3654.java b/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterDeleteProjectGroupTstDISABLED3654.java new file mode 100644 index 0000000000000000000000000000000000000000..58eadf20109fb50c3b9cf94169cd7b253e80bfc8 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterDeleteProjectGroupTstDISABLED3654.java @@ -0,0 +1,119 @@ +package org.olat.test.functional.codepoints.cluster; + +import org.junit.Ignore; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointClientFactory; +import org.olat.testutils.codepoints.client.CodepointRef; + +@Ignore +public class MultiBrowserClusterDeleteProjectGroupTstDISABLED3654 extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.RESTARTED_TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos user1 = context.createuserIfNotExists(1, "mbcnla1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "mbcnla2", standardPassword, true, true, true, true, true); + + { + System.out.println("logging in browser 1..."); + selenium1 = context.createSeleniumAndLogin(user1); + selenium1.click("ui=tabs::groups()"); + selenium1.waitForPageToLoad("30000"); + assertEquals("OLAT - Groups", selenium1.getTitle()); + + // delete the group if it already exists + if (selenium1.isElementPresent("ui=groups::content_deleteGroup(nameOfGroup=deleteprojectgrouptest)")) { + selenium1.click("ui=groups::content_deleteGroup(nameOfGroup=deleteprojectgrouptest)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=groups::content_deleteYes()"); + selenium1.waitForPageToLoad("30000"); + } + + // create the group + selenium1.click("ui=groups::toolbox_create_projectGroup()"); + selenium1.waitForPageToLoad("30000"); + assertEquals("OLAT - Groups", selenium1.getTitle()); + selenium1.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Group name)", "deleteprojectgrouptest"); + selenium1.click("ui=commons::flexiForm_finishButton()"); + selenium1.waitForPageToLoad("30000"); + assertEquals("OLAT - deleteprojectgrouptest", selenium1.getTitle()); + selenium1.click("ui=tabs::closeGroup(nameOfGroup=deleteprojectgrouptest)"); + selenium1.waitForPageToLoad("30000"); + + // add 'mbcnla2' as owner to the group + selenium1.click("ui=groups::content_clickGroupEntry(nameOfGroup=deleteprojectgrouptest)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=group::menu_administration()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=group::content_members_tabMembers()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=commons::usertable_owners_addUsers()"); + selenium1.waitForPageToLoad("30000"); + selenium1.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", "mbcnla2"); + selenium1.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium1.waitForPageToLoad("30000"); + selenium1.check("ui=commons::usertable_adduser_checkUsername(nameOfUser=mbcnla2)"); + selenium1.click("ui=commons::usertable_adduser_choose()"); + selenium1.waitForPageToLoad("30000"); + //selenium1.select("ui=commons::usertable_adduser_sendEmailSwitch()", "label=No"); + selenium1.click("ui=commons::usertable_adduser_finish()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=tabs::closeGroup(nameOfGroup=deleteprojectgrouptest)"); + selenium1.waitForPageToLoad("30000"); + + // click on 'delete group' now + selenium1.click("ui=groups::content_deleteGroup(nameOfGroup=deleteprojectgrouptest)"); + selenium1.waitForPageToLoad("30000"); + } + + + { + System.out.println("logging in browser 2..."); + selenium2 = context.createSeleniumAndLogin(user2); + + selenium2.click("ui=tabs::groups()"); + selenium2.waitForPageToLoad("30000"); + assertEquals("OLAT - Groups", selenium2.getTitle()); + + // click on 'delete group' now + selenium2.click("ui=groups::content_deleteGroup(nameOfGroup=deleteprojectgrouptest)"); + selenium2.waitForPageToLoad("30000"); + } + + CodepointClient codepointClientA = context.createCodepointClient(1); + CodepointRef createAreaCpA = codepointClientA.getCodepoint("org.olat.group.BusinessGroupManagerImpl.deleteBusinessGroupWithMail"); + createAreaCpA.setHitCount(0); + createAreaCpA.enableBreakpoint(); + + CodepointClient codepointClientB = context.createCodepointClient(2); + CodepointRef createAreaCpB = codepointClientB.getCodepoint("org.olat.group.BusinessGroupManagerImpl.deleteBusinessGroupWithMail"); + createAreaCpB.setHitCount(0); + createAreaCpB.enableBreakpoint(); + + selenium1.click("ui=groups::content_deleteYes()"); + selenium2.click("ui=groups::content_deleteYes()"); + + createAreaCpA.assertBreakpointReached(1, 10000); + createAreaCpB.assertBreakpointReached(1, 10000); + + createAreaCpA.disableBreakpoint(true); + createAreaCpB.disableBreakpoint(true); + + selenium1.waitForPageToLoad("30000"); + selenium2.waitForPageToLoad("30000"); + + // check that the group is gone + // note[se]: since the test currently fails with an exception, it is hard to tell what the exact assertion here should be for the OK case... + // one of the two should probably get a warning saying that the group was deleted by someone else at the same time - or nothing, since it was successfully deleted - just not by the person him/herself... + assertFalse(selenium1.isElementPresent("ui=groups::content_clickGroupEntry(nameOfGroup=deleteprojectgrouptest)")); + assertFalse(selenium2.isElementPresent("ui=groups::content_clickGroupEntry(nameOfGroup=deleteprojectgrouptest)")); + } +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterNewLearningAreaTstDisabled3440.java b/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterNewLearningAreaTstDisabled3440.java new file mode 100644 index 0000000000000000000000000000000000000000..8f2d0b5e09c6ece753203b7523e8ecf3e3b75293 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/MultiBrowserClusterNewLearningAreaTstDisabled3440.java @@ -0,0 +1,111 @@ +package org.olat.test.functional.codepoints.cluster; + +import org.junit.Ignore; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; + +@Ignore +public class MultiBrowserClusterNewLearningAreaTstDisabled3440 extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OlatLoginInfos user1 = context.createuserIfNotExists(1, "mbcnla1", "passwd08", true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "mbcnla2", "passwd08", true, true, true, true, true); + + { + System.out.println("logging in browser 1..."); + selenium1 = context.createSeleniumAndLogin(user1); + selenium1.click("ui=tabs::learningResources()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::menu_searchForm()"); + selenium1.waitForPageToLoad("30000"); + selenium1.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium1.click("ui=learningResources::content_searchForm_search()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::content_showContent()"); + selenium1.waitForPageToLoad("30000"); + + selenium1.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium1.waitForPageToLoad("30000"); + + // make sure the learning area does not exist yet - delete otherwise + selenium1.click("ui=groupManagement::menu_allLearningAreas()"); + selenium1.waitForPageToLoad("30000"); + if (selenium1.isElementPresent("ui=groupManagement::content_learningAreaTable_deleteLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)")) { + selenium1.click("ui=groupManagement::content_learningAreaTable_deleteLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=dialog::Yes()"); + selenium1.waitForPageToLoad("30000"); + } + + selenium1.click("ui=groupManagement::toolbox_groupManagement_newLearningArea()"); + selenium1.waitForPageToLoad("30000"); + + assertTrue(selenium1.isTextPresent("Create a new learning area")); + + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", "multibrowserclusterlearningarea"); + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_description()", "egal oder?"); + } + + { + System.out.println("logging in browser 2..."); + selenium2 = context.createSeleniumAndLogin(user2); + selenium2.click("ui=tabs::learningResources()"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::menu_searchForm()"); + selenium2.waitForPageToLoad("30000"); + selenium2.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium2.click("ui=learningResources::content_searchForm_search()"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::content_showContent()"); + selenium2.waitForPageToLoad("30000"); + + selenium2.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium2.waitForPageToLoad("30000"); + + selenium2.click("ui=groupManagement::toolbox_groupManagement_newLearningArea()"); + selenium2.waitForPageToLoad("30000"); + + assertTrue(selenium2.isTextPresent("Create a new learning area")); + selenium2.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", "multibrowserclusterlearningarea"); + selenium2.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_description()", "egal oder?"); + } + + CodepointClient codepointClientA = context.createCodepointClient(1); + CodepointRef createAreaCpA = codepointClientA.getCodepoint("org.olat.group.ui.NewAreaController.createArea"); + createAreaCpA.setHitCount(0); + createAreaCpA.enableBreakpoint(); + + CodepointClient codepointClientB = context.createCodepointClient(2); + CodepointRef createAreaCpB = codepointClientB.getCodepoint("org.olat.group.ui.NewAreaController.createArea"); + createAreaCpB.setHitCount(0); + createAreaCpB.enableBreakpoint(); + + selenium1.click("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()"); + selenium2.click("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()"); + + createAreaCpA.assertBreakpointReached(1, 10000); + createAreaCpB.assertBreakpointReached(1, 10000); + + createAreaCpA.disableBreakpoint(true); + createAreaCpB.disableBreakpoint(true); + + selenium1.waitForPageToLoad("30000"); + selenium2.waitForPageToLoad("30000"); + + assertTrue("Not found in selenium 1: Edit learning area multibrowserclusterlearningarea", selenium1.isTextPresent("Edit learning area multibrowserclusterlearningarea")); + assertTrue("Not found in selenium 2: The name of this learning area is already used in this group management, please select another.", selenium2.isTextPresent("The name of this learning area is already used in this group management, please select another.")); + } +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/NewLearningGroupTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/NewLearningGroupTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f12345c06f4f2ac320141362b581e8504ce35aa7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/NewLearningGroupTest.java @@ -0,0 +1,108 @@ +package org.olat.test.functional.codepoints.cluster; + +import com.thoughtworks.selenium.Selenium; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; + +/** + * + * Tests that one cannot use the same name for creating two groups. + * This test uses codepoints. + * + * @author eglis + * + */ +public class NewLearningGroupTest extends BaseSeleneseTestCase { + + protected Selenium selenium1; + protected Selenium selenium2; + + private String COURSE_NAME = Context.DEMO_COURSE_NAME_2; + private final String GROUP_NAME = "multibrowserclusterlearninggroup"; + + /** + * admin1 and admin2 open COURSE_NAME/Group management/Create group by use same group name. + * Only one user should succeed to create a group with the given title, the other one should get a warning: "This group name is already being used in this context..." + * + * @throws Exception + */ + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos user1 = context.createuserIfNotExists(1, "mbcnla1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "mbcnla2", standardPassword, true, true, true, true, true); + + { + System.out.println("logging in browser 1..."); + OLATWorkflowHelper workflow1 = context.getOLATWorkflowHelper(user1); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + GroupManagement groupManagement1 = courseRun1.getGroupManagement(); + + // make sure the learning group does not exist yet - delete otherwise + groupManagement1.deleteGroup(GROUP_NAME); + + selenium1 = groupManagement1.getSelenium(); + selenium1.click("ui=groupManagement::menu_allLearningGroups()"); + selenium1.waitForPageToLoad("30000"); + + selenium1.click("ui=groupManagement::toolbox_groupManagement_newLearningGroup()"); + selenium1.waitForPageToLoad("30000"); + + assertTrue(selenium1.isTextPresent("Create a new learning group")); + + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()", GROUP_NAME); + selenium1.type("ui=commons::tinyMce_styledTextArea()", "egal oder?"); + } + + { + System.out.println("logging in browser 2..."); + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(user2); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + selenium2 = courseRun2.getGroupManagement().getSelenium(); + + selenium2.click("ui=groupManagement::toolbox_groupManagement_newLearningGroup()"); + selenium2.waitForPageToLoad("30000"); + assertTrue(selenium2.isTextPresent("Create a new learning group")); + selenium2.type("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()", GROUP_NAME); + selenium2.type("ui=commons::tinyMce_styledTextArea()", "egal oder?"); + } + + CodepointClient codepointClientA = context.createCodepointClient(1); + CodepointRef createAreaCpA = codepointClientA.getCodepoint("org.olat.group.BusinessGroupFactory.createAndPersistLearningGroup"); + createAreaCpA.setHitCount(0); + createAreaCpA.enableBreakpoint(); + + CodepointClient codepointClientB = context.createCodepointClient(2); + CodepointRef createAreaCpB = codepointClientB.getCodepoint("org.olat.group.BusinessGroupFactory.createAndPersistLearningGroup"); + createAreaCpB.setHitCount(0); + createAreaCpB.enableBreakpoint(); + + selenium1.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + Thread.sleep(500); + selenium2.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + + createAreaCpA.waitForBreakpointReached(10000); + createAreaCpB.waitForBreakpointReached(10000); + + int pausedA = createAreaCpA.getPausedThreads()==null ? 0 : createAreaCpA.getPausedThreads().length; + int pausedB = createAreaCpB.getPausedThreads()==null ? 0 : createAreaCpB.getPausedThreads().length; + assertEquals("Asserts that there is only one thread that reached the codepoint.", 1, pausedA + pausedB); + + createAreaCpA.disableBreakpoint(true); + createAreaCpB.disableBreakpoint(true); + + selenium1.waitForPageToLoad("30000"); + selenium2.waitForPageToLoad("30000"); + + assertTrue(selenium1.isTextPresent("Edit group multibrowserclusterlearninggroup")); + assertTrue(selenium2.isTextPresent("This group name is already being used in this context, please select another one.")); + } +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/Open2NewFoTopicsTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/Open2NewFoTopicsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..be9669bf321191f64f5c2cf4d3885f4717485fcb --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/Open2NewFoTopicsTest.java @@ -0,0 +1,176 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.PageLoadWait; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +import com.thoughtworks.selenium.Selenium; + +/** + * Tests that the org.olat.course.nodes.FOCourseNode.doInSync codepoint works correctly: that is no 2 threads could get + * into the doInSync block at any time. + * <br/> + * + * Test setup: + * Needs a clean "Demo Course" with a "Forum" node. + * Creates 2 message topics suppose that a "Forum" node doesn't have any topics yet, + * and even more the node was not selected yet. + * <br/> + * + * Test case: <br/> + * 2 users try to open a new forum topic simultaneously. <br/> + * Asserts that only one thread reaches the FOCourseNode.doInSync codepoint at any time. + * + * @author Lavinia Dumitrescu + * + */ +public class Open2NewFoTopicsTest extends BaseSeleneseTestCase { + + protected Selenium selenium_A; + protected Selenium selenium_B; + private CodepointClient codepointClient_A; + private CodepointClient codepointClient_B; + + private String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "Demo Course 2NCp" + System.currentTimeMillis(); + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + //clone "Demo Course" and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + } + + + public void testOpen2NewFoTopics() throws Exception { + Context context = Context.getContext(); + + OLATWorkflowHelper workflow_A = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun_A = workflow_A.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + selenium_A = courseRun_A.getSelenium(); + + OLATWorkflowHelper workflow_s = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun_B = workflow_s.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + selenium_B = courseRun_B.getSelenium(); + + //codepoints node A + codepointClient_A = context.createCodepointClient(1); + CodepointRef beforeSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.nodes.FOCourseNode.beforeDoInSync"); + beforeSyncCp_A.setHitCount(0); + beforeSyncCp_A.enableBreakpoint(); + + CodepointRef doInSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.nodes.FOCourseNode.doInSync"); + doInSyncCp_A.setHitCount(0); + doInSyncCp_A.enableBreakpoint(); + + //codepoints node B + codepointClient_B = context.createCodepointClient(2); + CodepointRef beforeSyncCp_B = codepointClient_B.getCodepoint("org.olat.course.nodes.FOCourseNode.beforeDoInSync"); + beforeSyncCp_B.setHitCount(0); + beforeSyncCp_B.enableBreakpoint(); + + CodepointRef doInSyncCp_B = codepointClient_B.getCodepoint("org.olat.course.nodes.FOCourseNode.doInSync"); + doInSyncCp_B.setHitCount(0); + doInSyncCp_B.enableBreakpoint(); + + //select forum in node A + + courseRun_A.selectAnyButGetToRoot("Activation Interaction", PageLoadWait.NO_WAIT); + //check if codepoint reached, if yes continue + beforeSyncCp_A.assertBreakpointReached(1, 20000); + System.out.println("beforeSyncCp_A.assertBreakpointReached"); + TemporaryPausedThread[] threadsA = beforeSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + + doInSyncCp_A.assertBreakpointReached(1, 10000); + System.out.println("doInSyncCp_A.assertBreakpointReached"); + + //B stops at beforeSyncCp_B + courseRun_B.selectAnyButGetToRoot("Activation Interaction", PageLoadWait.NO_WAIT); + beforeSyncCp_B.assertBreakpointReached(1, 10000); + System.out.println("beforeSyncCp_B reached"); + + //continue B and check that the doInSyncCp_B was not reached + TemporaryPausedThread[] threadsB = beforeSyncCp_B.getPausedThreads(); + threadsB[0].continueThread(); + doInSyncCp_B.assertBreakpointNotReached(20000); + System.out.println("beforeSyncCp_B continues ... but doInSyncCp_B still not reached"); + + //continue A + threadsA = doInSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + System.out.println("doInSyncCp_A continues..."); + + //if doInSyncCp_B is reached, continue + doInSyncCp_B.assertBreakpointReached(1, 20000); + System.out.println("doInSyncCp_B reached"); + threadsB = doInSyncCp_B.getPausedThreads(); + threadsB[0].continueThread(); + System.out.println("doInSyncCp_B continues"); + + selenium_A.waitForPageToLoad("10000"); + courseRun_A.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + selenium_A.click("ui=course::content_forum_newTopic()"); + selenium_A.waitForPageToLoad("30000"); + System.out.println("A opens new topic"); + + selenium_B.waitForPageToLoad("10000"); + courseRun_B.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + selenium_B.click("ui=course::content_forum_newTopic()"); + selenium_B.waitForPageToLoad("30000"); + System.out.println("B opens new topic"); + + selenium_A.type("ui=course::content_forum_typeMsgTitle()", "CLUSTER <A> TOPIC"); + System.out.println("A types in a title"); + + selenium_B.type("ui=course::content_forum_typeMsgTitle()", "CLUSTER <B> TOPIC"); + System.out.println("B types in a title"); + + selenium_A.type("ui=course::content_forum_clickMsgBody()", "message body: CLUSTER A TOPIC"); + selenium_A.click("ui=course::content_forum_save()"); + selenium_A.waitForPageToLoad("30000"); + + selenium_B.type("ui=course::content_forum_clickMsgBody()", "message body: BBB BBBBBB BBBB"); + selenium_B.click("ui=course::content_forum_save()"); + selenium_B.waitForPageToLoad("30000"); + + selenium_A.click("ui=tabs::logOut()"); + selenium_B.click("ui=tabs::logOut()"); + + } + + @Override + public void cleanUpAfterRun() { + System.out.println("cleanUpAfterRun - START"); + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + System.out.println("cleanUpAfterRun - END"); + } + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/OpenNewFoTopicTest.java b/src/test/java/org/olat/test/functional/codepoints/cluster/OpenNewFoTopicTest.java new file mode 100644 index 0000000000000000000000000000000000000000..01f6fa4d36356ddf2b58aaeca461285b4161e777 --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/OpenNewFoTopicTest.java @@ -0,0 +1,126 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.codepoints.cluster; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.PageLoadWait; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.StructureElement; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +/** + * Tests that the org.olat.course.nodes.FOCourseNode.doInSync codepoint is reached. + * <br/> + * + * Test case: <br/> + * Opens a new Forum topic in a clean "Demo Course" with no forum threads into the "Forum" node. + * Asserts codepoint reached. + * + * @author Lavinia Dumitrescu + * + */ +public class OpenNewFoTopicTest extends BaseSeleneseTestCase { + + private CodepointClient codepointClient_A; + + private String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "OpenNewFoTopic" + System.currentTimeMillis(); + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + //clone "Demo Course" and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + } + + /** + * Opens a new Forum topic in a clean "Demo Course" with no forum threads into the "Forum" node. + * @throws Exception + */ + public void testOpenNewFoTopic() throws Exception { + Context context = Context.getContext(); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + + //open demo course copy + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + + //initialize codepoints + codepointClient_A = context.createCodepointClient(1); + CodepointRef beforeSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.nodes.FOCourseNode.beforeDoInSync"); + beforeSyncCp_A.setHitCount(0); + beforeSyncCp_A.enableBreakpoint(); + + CodepointRef doInSyncCp_A = codepointClient_A.getCodepoint("org.olat.course.nodes.FOCourseNode.doInSync"); + doInSyncCp_A.setHitCount(0); + doInSyncCp_A.enableBreakpoint(); + + //trigger "Activation Content" which in turn loads each of its children for displaying the Previews -> Changed behavior of test! + StructureElement selectActivation = courseRun.selectAnyButGetToRoot("Activation Interaction", PageLoadWait.NO_WAIT); + selenium = selectActivation.getSelenium(); + + // ASSERTION check if codepoint reached, if yes continue + beforeSyncCp_A.assertBreakpointReached(1, 10000); + System.out.println("beforeSyncCp_A.assertBreakpointReached"); + TemporaryPausedThread[] threadsA = beforeSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + + doInSyncCp_A.assertBreakpointReached(1, 10000); + System.out.println("doInSyncCp_A.assertBreakpointReached"); + threadsA = doInSyncCp_A.getPausedThreads(); //overwrite threadsA + threadsA[0].continueThread(); + + // activate actual "Forum" content for proceeding + selenium.waitForPageToLoad("30000");//wait for previous NO_WAITED Action + courseRun.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + + if(selenium.isElementPresent("ui=course::content_forum_displayForum()")) { + selenium.click("ui=course::content_forum_displayForum()"); + selenium.waitForPageToLoad("30000"); + } + + selenium.click("ui=course::content_forum_newTopic()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=course::content_forum_typeMsgTitle()", "TODAY'S TOPIC"); + selenium.type("ui=course::content_forum_clickMsgBody()", "message body"); + selenium.click("ui=course::content_forum_save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=tabs::logOut()"); + } + + @Override + public void cleanUpAfterRun() { + System.out.println("cleanUpAfterRun - START"); + LearningResources learningResources = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)).getLearningResources(); + learningResources.searchResource(COURSE_NAME, null).deleteLR(); + System.out.println("cleanUpAfterRun - END"); + } + + + +} diff --git a/src/test/java/org/olat/test/functional/codepoints/cluster/package.html b/src/test/java/org/olat/test/functional/codepoints/cluster/package.html new file mode 100644 index 0000000000000000000000000000000000000000..06ba4af2f7c0c9c007fb19fd63b19b9f7b1a2b0b --- /dev/null +++ b/src/test/java/org/olat/test/functional/codepoints/cluster/package.html @@ -0,0 +1,34 @@ +<html> +<head> +</head> + +<body> + +Codepoints tests for cluster setup. They run only against an OLAT instance configured as codepoint server. (selenium-cluster or selenium-single, not OLATNG) +<br/> +Run a codepoint test in eclipse using your local OLAT instance: + +<ul> + <li>start ActiveMQ</li> + <li> Configure your local olat with a codepoint server (enable/disable codepoint/breakpoint framework) + <ul><li>codepoint_server.enabled=true</li> + <li>codepoint.jms.broker.url=failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0)</li> + <li>(instance.id=myolat) remember this since must be used in customcontext.xml </li> + + </ul> + </li> + <li>start olat and check that it really starts as a codepoint server</li> + <li>configure customcontext.xml, namely: + <ul><li>key="jmsBrokerUrl", value="tcp://localhost:61616"</li> + <li>key="instanceId" value="myolat"</li> + </ul> + </li> + + <li>start codepoint tests. + + </li> +</ul> + + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/course/CopyCourseTest2.java b/src/test/java/org/olat/test/functional/course/CopyCourseTest2.java new file mode 100644 index 0000000000000000000000000000000000000000..1cf729556d21758f24b97a1499b5dd178a5cf9c3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/CopyCourseTest2.java @@ -0,0 +1,116 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.course; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests CourseFactory.copyCourse() in single VM mode - no codepoints. + * + * Test case: <br/> + * Creates 2 copies ("COPY A - DEMO COURSE" and "COPY B - DEMO COURSE") of the same "Demo Course", serial not parallel. <p> + * + * @author Lavinia Dumitrescu + * + */ +public class CopyCourseTest2 extends BaseSeleneseTestCase { + + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + private final String COURSE_NAME = "CopyCourse" + System.currentTimeMillis(); + private final String CLONE_A = "COPY A - DEMO COURSE"; + private final String CLONE_B = "COPY B - DEMO COURSE"; + + + + /** + * administrator adds author as owner of the "Demo Course" + */ + public void setUp() throws Exception { + System.out.println("CopyCourseTest - setUp - START"); + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + //cleanup first + WorkflowHelper.deleteAllCoursesNamed(CLONE_A); + WorkflowHelper.deleteAllCoursesNamed(CLONE_B); + + //clone "Demo Course" and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + //author + OlatLoginInfos authorOlatLoginInfos = context.getStandardAuthorOlatLoginInfos(1); + //"administrator" adds author as owner of the "Demo Course" + WorkflowHelper.addOwnerToLearningResource(authorOlatLoginInfos.getUsername(), COURSE_NAME); + System.out.println("CopyCourseTest - setUp - END"); + } + + /** + * Tests course copy in singleVM mode. + * Creates 2 copies ("COPY A - DEMO COURSE" and "COPY B - DEMO COURSE") of the same "Demo Course". <p> + * + * + * @throws Exception + */ + public void testCopyCourse2() throws Exception { + Context context = Context.getContext(); + + //administrator + OLATWorkflowHelper workflow_A = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + LRDetailedView lRDetailedView_A = workflow_A.getLearningResources().searchResource(COURSE_NAME, null); + + //author - owner of the "Demo Course" + OLATWorkflowHelper workflow_B = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + LRDetailedView lRDetailedView_B = workflow_B.getLearningResources().searchResource(COURSE_NAME, null); + + lRDetailedView_A.copyLR(CLONE_A, null); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + lRDetailedView_B.copyLR(CLONE_B, null); + + workflow_A.logout(); + workflow_B.logout(); + } + + + + /** + * Deletes the created copies. + */ + @Override + public void cleanUpAfterRun() { + System.out.println("CopyCourseTest - cleanUpAfterRun - START"); + + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + LearningResources learningResources = workflow.getLearningResources().searchResource(CLONE_A, null).deleteLR(); + learningResources.searchResource(CLONE_B, null).deleteLR(); + + System.out.println("CopyCourseTest - cleanUpAfterRun - END"); + } +} diff --git a/src/test/java/org/olat/test/functional/course/CourseCloseTest.java b/src/test/java/org/olat/test/functional/course/CourseCloseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fd945b479b01bb489dfdd74d9c42d5a8cec920c3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/CourseCloseTest.java @@ -0,0 +1,137 @@ +package org.olat.test.functional.course; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.selenium.olatapi.group.RightsAdmin; +import org.olat.test.util.selenium.olatapi.group.RightsManagement; +import org.olat.test.util.selenium.olatapi.lr.Catalog; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * Tests the close course functionality + * <br /> + * Test setup: + * <br /> + * 1. login with role "author" + * 2. create an empty course + * 3. publish empty course + * 4. create learning group and rights group for that course + * 5. add course to catalog + * 6. close course + * 7. check that course is no longer in catalog and groups are empty + * + * + * @author Thomas Linowsky, BPS GmbH + * + */ + +public class CourseCloseTest extends BaseSeleneseTestCase{ + + private static String author; + + private static final String COURSE_NAME_PREFIX = "CloseCourse"; + + private final String COURSE_NAME = COURSE_NAME_PREFIX + System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription" + System.currentTimeMillis(); + + private final String ASSIGNMENT_NAME= "Enrollment"+System.currentTimeMillis(); + + private final String LEARNING_GROUP_NAME = COURSE_NAME_PREFIX+"LearningGroup"+System.currentTimeMillis(); + private final String LEARNING_GROUP_DESC = "LearningGroupDesc"+System.currentTimeMillis(); + + private final String RIGHTS_GROUP_NAME= COURSE_NAME_PREFIX+"RightsGroupName"+System.currentTimeMillis(); + private final String RIGHTS_GROUP_DESC= "RightsGroupDesc"+System.currentTimeMillis(); + + @Override + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + author = context.getStandardAuthorOlatLoginInfos().getUsername(); + + WorkflowHelper.deleteLearningResources(author, COURSE_NAME_PREFIX); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + CourseEditor editor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + // make sure course is not empty + editor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, ASSIGNMENT_NAME); + editor.publishCourse(); + + CourseRun run = editor.closeToLRDetailedView().showCourseContent(); + + // create a learning group and add author to it + GroupManagement learn = run.getGroupManagement(); + GroupAdmin lg = learn.createLearningGroup(LEARNING_GROUP_NAME, LEARNING_GROUP_DESC, 25, true, false); + String[] names = new String[]{author}; + lg.addMembers(names, new String[0]); + run = learn.close(); + + // create a rights group and add author to it + RightsManagement rights = run.getRightsManagement(); + RightsAdmin rga = rights.createRightsGroup(RIGHTS_GROUP_NAME, RIGHTS_GROUP_DESC); + rga.addMembers(names); + LRDetailedView detail = rights.closeRightsManagement().getDetailedView(); + // add the course to the catalog + detail.addToCatalog(); + olatWorkflow.logout(); + } + + public void testCloseCourse() throws Exception{ + + Context context = Context.getContext(); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + LRDetailedView detail = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME); + + // make sure the groups are there + Groups g = olatWorkflow.getGroups(); + assertTrue("Group "+LEARNING_GROUP_NAME+" is not present but should be", g.hasGroup(LEARNING_GROUP_NAME)); + assertTrue("Group "+RIGHTS_GROUP_NAME+" is not present but should be", g.hasGroup(RIGHTS_GROUP_NAME)); + + // make sure the course is in the catalog + Catalog catalog = olatWorkflow.getLearningResources().showCatalog(); + assertTrue(catalog.isEntryAvailable(COURSE_NAME)); + + detail = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME); + + // close course + detail.closeCourse(true, true); + + assertTrue("could not find \"[Closed]\" in Detail Page", detail.isTextPresent("[closed]")); + + CourseRun run = detail.showCourseContent(); + assertTrue("could not find \"is closed\"-message", run.isTextPresent("This course is closed and can therefore no longer be edited or updated")); + + g = olatWorkflow.getGroups(); + // refresh group view, otherwise groups will still be displayed although not available anymore + g = olatWorkflow.getGroups(); + + // check that the groups are empty now + assertFalse("Group "+LEARNING_GROUP_NAME+" is still present but should not be", g.hasGroup(LEARNING_GROUP_NAME)); + assertFalse("Group "+RIGHTS_GROUP_NAME+" is still present but should not be", g.hasGroup(RIGHTS_GROUP_NAME)); + + // make sure the course is no longer in the catalog + catalog = olatWorkflow.getLearningResources().showCatalog(); + assertFalse("Course "+COURSE_NAME+" is still present in Catalog but should not be!", catalog.isEntryAvailable(COURSE_NAME)); + + // delete the course in the end + detail = olatWorkflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getDetailedView(); + detail.deleteLR(); + } + + @Override + protected void cleanUpAfterRun() { + super.cleanUpAfterRun(); + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + } + +} diff --git a/src/test/java/org/olat/test/functional/course/CourseWizardVisibiltyTest.java b/src/test/java/org/olat/test/functional/course/CourseWizardVisibiltyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..49e34c95717eaa2ef1999881626208359540270e --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/CourseWizardVisibiltyTest.java @@ -0,0 +1,93 @@ +package org.olat.test.functional.course; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.lr.Catalog; +import org.olat.test.util.selenium.olatapi.lr.CourseWizard; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * Tests the course wizard + * 1. author creates course using the course wizard + * 2. select all items (singlepage, enrollment, downloadfolder, forum and contact form) to create + * 3. edit the enrollment configuration + * 4. select all available CBBs (singlepage, downloadfolder, forum and contact form) for access restriction + * 5. publish course and run it + * 6. enrol in created group and show forum + * 7. log out + * @author Thomas Linowsky + * + */ + +public class CourseWizardVisibiltyTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseWizard" + System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription" + System.currentTimeMillis(); + private final String ASSESSMENT_NAME = "Assessment"+System.currentTimeMillis(); + private final String ENROLMENT_NAME = "Enrollment"; + private final String GROUP_NAME = COURSE_NAME + " Group 1"; + private final String SINGLE_PAGE_NAME ="Information page"; + + public void testVisibility() { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + // get the wizard object + CourseWizard wizard = olatWorkflow.getLearningResources().createCourseWizard(COURSE_NAME, COURSE_DESCRIPTION); + + // select all elements that are possible + wizard.selectCourseElements(true, true, true, true, true); + // define that all possible CBBs are only visible when enrolled + wizard.editEnrollment(true, true, true, true, true); + + // finish course wizard and define visibility status + CourseRun run = wizard.createCourseAndRun(LRDetailedView.ACCESS_ALL_REGISTERED); + + // enrol author + EnrolmentRun enrol = run.selectEnrolment(ENROLMENT_NAME); + enrol.enrol(GROUP_NAME); + + // check the access rule + LRDetailedView detail = run.getDetailedView(); + assertTrue("Acess rule does not match "+LRDetailedView.ACCESS_ALL_REGISTERED+", it is "+detail.getAccessString(), detail.getAccessString().equals(LRDetailedView.ACCESS_ALL_REGISTERED)); + + Catalog catalog = olatWorkflow.getLearningResources().showCatalog(); + assertTrue("could not find "+COURSE_NAME+" in the catalog", catalog.isEntryAvailable(COURSE_NAME)); + + // the the editor again + run = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME).showCourseContent(); + CourseEditor editor = run.getCourseEditor(); + + // make sure the storage folder is available + Folder storage = editor.storageFolder(); + editor = storage.closeStorageFolder(); + + // delete the information page and add an assessment to make sure the course is correct + editor.selectCourseElement(SINGLE_PAGE_NAME); + editor.deleteCourseElement(); + editor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, ASSESSMENT_NAME); + editor.publishCourse(); + run = editor.closeToCourseRun(); + + + + // make sure the information page is deleted and the assessment is available + assertFalse("Information page is still present but should not be!", run.isElementPresent("ui=course::menu_courseNode(titleOfNode=Information page)")); + assertTrue("assessment "+ASSESSMENT_NAME+" is not present but should be!", run.isElementPresent("ui=course::menu_courseNode(titleOfNode="+ASSESSMENT_NAME+")")); + + // delete the course + detail = run.getDetailedView(); + detail.deleteLR(); + olatWorkflow.logout(); + } + +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/AssessmentElementTest.java b/src/test/java/org/olat/test/functional/course/assessment/AssessmentElementTest.java new file mode 100644 index 0000000000000000000000000000000000000000..92c32cec96d228e44ef0c5947f4fbc87452dd7ea --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/AssessmentElementTest.java @@ -0,0 +1,153 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.course.assessment; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.AssessmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.home.EvidencesOfAchievement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the assessment course element, assessment tool and the evidence of achievement. + * <br/> + * Test setup:<br/> + * 1. clean-up: deleteEvidencesOfAchievement for this student, starting with COURSE_NAME_PREFIX. Delete courses starting with COURSE_NAME_PREFIX.<br/> + * 2. administrator imports test course <br/> + * 3. adds author as owner of the COURSE_NAME <br/> + * 4. adds author as tutor of the group GROUP_NAME <br/> + * 5. student enrolls into group <br/> + * <p> + * Test case: <br/> + * 1. author adds new Assessment course element in course and configures it. (min, max score, passed cut value, etc.) <br/> + * 2. publish course <br/> + * 3. author checks in the assessment tool the stored values for the assessment form: min/max score, passed cut value <br/> + * 4. author grants score to student, and checks if the passed is correctly computed <br/> + * 5. Student checks the score/passed info in the "Evidence of achievement". <br/> + * + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentElementTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private final String COURSE_NAME_PREFIX = "AssessmentTool_selenium"; + private final String COURSE_NAME = COURSE_NAME_PREFIX + System.currentTimeMillis(); + private final String GROUP_NAME = "Gruppe 1"; + private final String ASSESSMENT_ELEMENT_TITLE = "Assessment_NEW"; + + private String STUDENT1 = "test"; + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //author adds participants to group or student enrolls in group + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + OlatLoginInfos olatLoginInfos1 = context.getStandardStudentOlatLoginInfos(1); + STUDENT1 = olatLoginInfos1.getUsername(); + + //cleanup first - for the selenium load + WorkflowHelper.deleteEvidencesOfAchievement(COURSE_NAME_PREFIX, olatLoginInfos1); + WorkflowHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX); + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds author as owner of the COURSE_NAME + WorkflowHelper.addOwnerToLearningResource(context.getStandardAuthorOlatLoginInfos(1).getUsername(),COURSE_NAME); + + //add author as tutor of the group + WorkflowHelper.addTutorToGroup(context.getStandardAuthorOlatLoginInfos(1).getUsername(), COURSE_NAME, GROUP_NAME); + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(olatLoginInfos1); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentElement = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + if(!enrolmentElement.alreadyEnrolled(GROUP_NAME)) { + enrolmentElement.enrol(GROUP_NAME); + assertTrue(enrolmentElement.isTextPresent("You have already enroled for the learning group mentioned below")); + } + } + + + + public void testAssessmentElement() throws Exception { + Context context = Context.getContext(); + + //author - owner of the COURSE_NAME + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + AssessmentEditor assessmentEditor = (AssessmentEditor)courseEditor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, ASSESSMENT_ELEMENT_TITLE); + // author fills in the assessment configuration form + assessmentEditor.configure(true, 1, 10, true, 5); + Thread.sleep(1000); + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToCourseRun(); + // author opens the AssessmentTool and checks the configured values for the newly introduced Assessment course element + AssessmentTool assessmentTool = courseRun.getAssessmentTool(); + AssessmentForm assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE); + // check values for min/max score, passed cut value + assertEquals("1.0", assessmentForm.getMinScore()); + assertEquals("10.0", assessmentForm.getMaxScore()); + assertEquals("5.0", assessmentForm.getPassedCutScore()); + // fills the form + assessmentForm.setScore(7); + assessmentTool = assessmentForm.save(); + // check values in the assessment table (score, passed) + assertEquals("7.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + assertEquals("Passed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + + //tutor changes score to 4 + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE); + assessmentForm.setScore(4); + assessmentForm.save(); + // check values in the assessment table (score, passed) + assertEquals("4.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + assertEquals("Failed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + + //student check the "Evidence of achievement" + OLATWorkflowHelper workflow_S = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun_S = workflow_S.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EvidencesOfAchievement evidences = workflow_S.getHome().getEvidencesOfAchievement(); + evidences.selectDetails(COURSE_NAME); + //check score in table + assertEquals("4.000", evidences.getCourseElementScore(ASSESSMENT_ELEMENT_TITLE)); + assertEquals("Failed", evidences.getCourseElementPassedStatus(ASSESSMENT_ELEMENT_TITLE)); + } + + +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/AssessmentFormTest.java b/src/test/java/org/olat/test/functional/course/assessment/AssessmentFormTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4528091373f02171254b50ff3ec387b9315f13d6 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/AssessmentFormTest.java @@ -0,0 +1,202 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.functional.course.assessment; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.home.EvidencesOfAchievement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests that all inputs in AssessmentForm (AssessmentTool) are correctly stored and seen by the student + * in different cluster nodes.<br/> + * + * Test setup: <br/> + * 1. import course <br/> + * 2. add standard author as owner to imported course <br/> + * 3. add standard author as tutor to group <br/> + * 4. standard student enrolls in group <br/> + * + * Test case: <br/> + * Tests whether all inputs in AssessmentForm are correctly stored and correctly seen by the tutor in AssessmentTool and + * the student in course run and in the "Evidence of achievement". + * The AssessmentForm is used for assessing: Test, Task and Assessment course elements. + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentFormTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private final String COURSE_NAME = "AssessmentTool_selenium" +System.currentTimeMillis(); + private final String GROUP_NAME = "Gruppe 1"; + + private String STUDENT1 = "test"; + private final String COMMENT_TXT = "comment_for_user"; + + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //author adds participants to group or student enrolls in group + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + OlatLoginInfos olatLoginInfos1 = context.getStandardStudentOlatLoginInfos(1); + STUDENT1 = olatLoginInfos1.getUsername(); + + //cleanup first - only if the course name is reused + /*OlatServerSetupHelper.deleteEvidenceOfAchievement(COURSE_NAME, olatLoginInfos1); + OlatServerSetupHelper.deleteAllCoursesNamed(COURSE_NAME);*/ + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds author as owner of the COURSE_NAME + WorkflowHelper.addOwnerToLearningResource(context.getStandardAuthorOlatLoginInfos(1).getUsername(),COURSE_NAME); + + //add author as tutor of the group + WorkflowHelper.addTutorToGroup(context.getStandardAuthorOlatLoginInfos(1).getUsername(), COURSE_NAME, GROUP_NAME); + + enrollInGroupAfterLogin(olatLoginInfos1, COURSE_NAME, GROUP_NAME); + } + + private void enrollInGroupAfterLogin(OlatLoginInfos olatLoginInfos, String courseName, String groupName) { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(olatLoginInfos); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(courseName); + EnrolmentRun enrolmentElement = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + if(!enrolmentElement.alreadyEnrolled(groupName)) { + enrolmentElement.enrol(groupName); + assertTrue(enrolmentElement.isTextPresent("You have already enroled for the learning group mentioned below")); + } + workflow.logout(); + } + + + public void testFormAssessmentTest() throws Exception { + Context context = Context.getContext(); + OLATWorkflowHelper workflow_S = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun_S = workflow_S.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + // setup: student runs the test first time ("Test 1" and gets a score equals with 2) + courseRun_S.selectCourseElement("Struktur 1"); + TestRun testRun = courseRun_S.selectTest("Test 1").startTest(); + testRun.selectMenuItem("Single Choice"); + testRun.setSingleChoiceSolution("Antwort 3"); + testRun.selectMenuItem("Multiple Choice"); + String[] answers = {"Antwort 2", "Antwort 3"}; + testRun.setMultipleChoiceSolution(answers); + // student achieved score: 2 + TestElement testElement_S = testRun.finishTest(true, 2); + assertEquals("2.000", testElement_S.getAchievedScore()); + // end setup - student achieved a score of 2.000 + + //author - tutor of the default group - opens the AssessmentTool and assess student + OLATWorkflowHelper workflow_A = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + AssessmentTool assessmentTool = workflow_A.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getAssessmentTool(); + String score = assessmentTool.getScoreInTableAsPerUser(STUDENT1, "Test 1", false); + String passed = assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, "Test 1", false); + assertEquals("2.000", score); + assertEquals("Passed", passed); + + // author selects "Test 1" and fills in the form - attempts:7, score: 7, passed: true + AssessmentForm assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, "Test 1"); + assertEquals("2.000", assessmentForm.getScore()); + assessmentForm.setAttempts(7); + assessmentForm.setScore(7); + assessmentForm.setPassed(true); + assessmentForm.setUserComments(COMMENT_TXT); + assessmentTool = assessmentForm.save(); + // check in table the update of the values + assertEquals("7.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, "Test 1", false)); + assertEquals("7", assessmentTool.getAttemptsInTableAsPerUser(STUDENT1, "Test 1", false)); + assertEquals("Passed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, "Test 1", false)); + + // author selects "Test 1" and fills in the form + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, "Test 1"); + + //author checks the previous stored values in AssessmentForm + assertEquals("7.000", assessmentForm.getScore()); + assertEquals("7", assessmentForm.getAttempts()); + assertEquals(AssessmentForm.PASSED_YES, assessmentForm.getPassed()); + assertEquals(COMMENT_TXT, assessmentForm.getUserComment()); + + //author changes inputs - attempts:6, score: 6, passed: false + assessmentForm.setAttempts(6); + assessmentForm.setScore(6); + assessmentForm.setPassed(false); + assessmentTool = assessmentForm.save(); + // check in table the update of the values + assertEquals("6.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, "Test 1", false)); + assertEquals("6", assessmentTool.getAttemptsInTableAsPerUser(STUDENT1, "Test 1", false)); + assertEquals("Failed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, "Test 1", false)); + + //author changes the score evaluation for the "Bewertung 1" element, that reset it to the original values + //tests that the PASSED info could be reset + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, "Bewertung 1"); + assessmentForm.setScore(3); + assessmentForm.setPassed(true); + assessmentTool = assessmentForm.save(); + assertEquals("3.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, "Bewertung 1", false)); + assertEquals("Passed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, "Bewertung 1", false)); + + //reset form + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, "Bewertung 1"); + assessmentForm.setScore(0); + assessmentForm.setPassed(null); + assessmentTool = assessmentForm.save(); + assertEquals("0.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, "Bewertung 1", false)); + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, "Bewertung 1"); + assertEquals(AssessmentForm.PASSED_NO_INFO, assessmentForm.getPassed()); + + //student checks the results in course run + TestElement testElement = courseRun_S.selectTest("Test 1"); + assertEquals("6.000", testElement.getAchievedScore()); + assertEquals("Failed", testElement.getStatus()); + assertEquals(COMMENT_TXT, testElement.getCommentFromTutor()); + + //student checks "Evidence of achievement" in HOME - show details + EvidencesOfAchievement evidencesOfAchievement = workflow_S.getHome().getEvidencesOfAchievement(); + evidencesOfAchievement.selectDetails(COURSE_NAME); + // check score in table + assertEquals("6.000", evidencesOfAchievement.getCourseElementScore("Test 1")); + assertEquals("6", evidencesOfAchievement.getCourseElementAttempts("Test 1")); + assertEquals("Failed", evidencesOfAchievement.getCoursePassedStatus("Test 1")); + assertEquals("0.000", evidencesOfAchievement.getCourseElementScore("Bewertung 1")); + + workflow_A.logout(); + } + +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/AssessmentTest.java b/src/test/java/org/olat/test/functional/course/assessment/AssessmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..30bc99ace778478b6114bc7ef9c9d284b81da32b --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/AssessmentTest.java @@ -0,0 +1,224 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ + +package org.olat.test.functional.course.assessment; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.StructureEditor; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.course.run.StructureElement; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.home.EvidencesOfAchievement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests the Assessment (AssessmentTool, TestRun, EfficiencyStatement) - cluster mode. + * + * Test setup: <br/> + * Expects a special "AssessmentTool" course. This must be imported. <br/> + * It is also supposed that there is a learning group associated with this course which contains at least + * one student and one tutor. <br/> + * + * Test case: <br/> + * - Student runs a test (Test 1) in a special "AssessmentTool" course. <br/> + * - Tutor opens the assessment tool of the same course for the specified student and checks whether he see the correct score. <br/> + * - Tutor changes the score (3) and passed value (Yes) of the Assessment course element: "Bewertung 1". <br/> + * - Tutor checks the parent Structure node score (Struktur 1). <br/> + * - Student runs the test (Test 1) second time and achieves 2 points. + * - Tutor increases the score to 4. The student should see the latest score. + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private OLATWorkflowHelper workflow_A; //student on node 1 + private OLATWorkflowHelper workflow_B; //tutor on node 2 + + private final String COURSE_NAME = "AssessmentTool_selenium" +System.currentTimeMillis(); + private final String GROUP_NAME = "Gruppe 1"; + + //test actors + private String STUDENT; //student username + private String TUTOR; // tutor username + + public void setUp() throws Exception { + System.out.println("AssessmentTest - setUp - STARTED"); + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //cleanup first - only if the course name is reused + /*OlatServerSetupHelper.deleteEvidenceOfAchievement(COURSE_NAME, context.getStandardStudentOlatLoginInfos(1)); + OlatServerSetupHelper.deleteAllCoursesNamed(COURSE_NAME);*/ + + TUTOR = context.getStandardAuthorOlatLoginInfos(2).getUsername(); + STUDENT = context.getStandardStudentOlatLoginInfos(1).getUsername(); + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds tutor as owner of the "AssessmentTool" + WorkflowHelper.addOwnerToLearningResource(TUTOR, COURSE_NAME); + + //"administrator" adds tutor to GROUP_NAME + WorkflowHelper.addTutorToGroup(TUTOR, COURSE_NAME, GROUP_NAME); + + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + OLATWorkflowHelper workflow_D = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + CourseRun courseRun = workflow_D.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + enrolmentRun.enrol(GROUP_NAME); + assertTrue(enrolmentRun.isTextPresent("You have already enroled for the learning group mentioned below")); + + OLATWorkflowHelper authorWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + resetScoreCalculationRule(authorWorkflow, 10); + + System.out.println("AssessmentTest - setUp - ENDED"); + } + + + public void testRunTest() throws Exception { + System.out.println("AssessmentTest - testRunTest - STARTED"); + Context context = Context.getContext(); + + workflow_A = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + workflow_B = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + CourseRun courseRun_A = workflow_A.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + CourseRun courseRun_B = workflow_B.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + + // STUDENT runs the "Test 1" and gets a score equals with 1. + courseRun_A.selectCourseElement("Struktur 1"); + TestRun testRun_A = courseRun_A.selectTest("Test 1").startTest(); + testRun_A.selectMenuItem("Single Choice"); + testRun_A.setSingleChoiceSolution("Antwort 3"); + TestElement testElement_A = testRun_A.finishTest(true, 1); //updateEfficiencyStatement(1) + assertEquals("1.000", testElement_A.getSelenium().getText("ui=qti::yourScore()")); + + // tutor opens the assessment tool of the same course + AssessmentTool assessmetTool = courseRun_B.getAssessmentTool(); + assertEquals("1.000",assessmetTool.getScoreInTableAsPerUser(STUDENT,"Test 1", false)); + AssessmentForm assessmentForm = assessmetTool.getAssessmentFormAsPerUser(STUDENT, "Bewertung 1"); + assessmentForm.setScore(3); + assessmentForm.setPassed(Boolean.TRUE); + assessmetTool = assessmentForm.save(); //updateEfficiencyStatement(2) + // assert score on "Struktur 1" to be the sum of the "Test 1" and "Bewertung 1" scores + assertEquals("4.000", assessmetTool.getSelenium().getText("ui=course::assessment_scoreInTable(title=Struktur 1)")); + //assert score on "Struktur 2" to be the half of sum of the "Test 1" and "Bewertung 1" scores + assertEquals("2.000", assessmetTool.getSelenium().getText("ui=course::assessment_scoreInTable(title=Struktur 2)")); + + //student runs the test second time ("Test 1" and gets a score equals with 2) + testRun_A = testElement_A.startTest(); + testRun_A.selectMenuItem("Single Choice"); + testRun_A.setSingleChoiceSolution("Antwort 3"); + testRun_A.selectMenuItem("Multiple Choice"); + String[] answers = {"Antwort 2", "Antwort 3"}; + testRun_A.setMultipleChoiceSolution(answers); + testElement_A = testRun_A.finishTest(true, 2); //updateEfficiencyStatement(3) + assertEquals("2.000", testElement_A.getSelenium().getText("ui=qti::yourScore()")); + + //tutor opens the Assessment form for STUDENT, "Test 1" and verify the score + assertEquals("2.000", assessmetTool.getScoreInTableAsPerUser(STUDENT,"Test 1", true)); + // verify score in AssessmentForm - select "Test 1" + assessmentForm = assessmetTool.getAssessmentFormAsPerUser(STUDENT, "Test 1"); + assessmentForm.setScore(4); + assessmentForm.setPassed(Boolean.TRUE); + assessmetTool = assessmentForm.save(); + //assert score on "Struktur 1" to be the sum of the "Test 1" and "Bewertung 1" scores + assertEquals("7.000", assessmetTool.getScoreInTableAsPerUser(STUDENT,"Struktur 1", false)); + //assert score on "Struktur 2" to be the half of sum of the "Test 1" and "Bewertung 1" scores + assertEquals("3.500", assessmetTool.getScoreInTableAsPerUser(STUDENT,"Struktur 2", false)); + + //A: close course + courseRun_A.close(COURSE_NAME); + + //B: close course + assessmetTool.close().close(COURSE_NAME); + + doTestRuleChange(); + + System.out.println("AssessmentTest - testRunTest - ENDED"); + } + + /** + * Tests the update of the scoreEvaluation (score/passed) in course for a student, + * and for a tutor in AssessmentTool after a change in the score calculation rule (CourseEditor/Score). + * This assumes that the passed cut value for this course is 10. + * The value will be next increased to 15 so the student should see the correct passed/failed information + * in her "Evidence of achievement". + */ + private void doTestRuleChange() throws Exception { + System.out.println("AssessmentTest - doTestRuleChange - STARTED"); + //student enters the "Evidence of achievement" - (score 10.5 and passed) + EvidencesOfAchievement evidencesOfAchievement = workflow_A.getHome().getEvidencesOfAchievement(); + String passedStatus = evidencesOfAchievement.getCoursePassedStatus(COURSE_NAME); + assertEquals("Passed",passedStatus); + // student enters course and checks her passed status + CourseRun courseRun_A = evidencesOfAchievement.startCourse(COURSE_NAME); + StructureElement root = courseRun_A.selectRoot(COURSE_NAME); + assertEquals("Passed", root.getPassedStatus()); + courseRun_A.close(COURSE_NAME); + + // tutor changes the score calculation rule and publishes the course + resetScoreCalculationRule(workflow_B, 15); + + // the student should get the updated (passed/failed) info + evidencesOfAchievement = workflow_A.getHome().getEvidencesOfAchievement(); + assertEquals("Failed", evidencesOfAchievement.getCoursePassedStatus(COURSE_NAME)); + passedStatus = evidencesOfAchievement.startCourse(COURSE_NAME).selectRoot(COURSE_NAME).getPassedStatus(); + assertEquals("Failed", passedStatus); + + workflow_A.logout(); + workflow_B.logout(); + + System.out.println("AssessmentTest - doTestRuleChange - ENDED"); + } + + + + /** + * tutor resets the score calculation rule and publishes the course + * + */ + private void resetScoreCalculationRule(OLATWorkflowHelper authorWorkflow , int score) { + CourseEditor courseEditor = authorWorkflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + StructureEditor structureEditor = (StructureEditor)courseEditor.selectCourseElement(COURSE_NAME); + structureEditor.setMinimumScore(score); + courseEditor.publishCourse(); + courseEditor.closeToCourseRun().close(COURSE_NAME); + } + + +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/BulkAssessmentTest.java b/src/test/java/org/olat/test/functional/course/assessment/BulkAssessmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1981c9672d1d7285ec40f34a31be0ff09bfd5dd0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/BulkAssessmentTest.java @@ -0,0 +1,173 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.functional.course.assessment; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentElement; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.home.EvidencesOfAchievement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests the bulk assessment in cluster mode. <br/> + * Test setup: <br/> + * 1. creates students (STUDENT1, STUDENT2, STUDENT3) <br/> + * 2. import course (AssessmentTool) and name it COURSE_NAME <br/> + * 3. adds author as owner of the course <br/> + * 4. adds author as tutor of the group GROUP_NAME <br/> + * 5. students enroll in group <br/> + * <p> + * Test case: <br/> + * Tutor (node 1) opens the AssessmentTool of the COURSE_NAME, starts the bulk assessment wizard and + * adds score values for a ASSESSMENT_ELEM_NAME course element for 3 users enrolled into the group. + * The scores are: 2, 3, and 4 for STUDENT1, STUDENT2, STUDENT3. + * <br/> + * STUDENT2 asserts his score in course run (COURSE_NAME) for the ASSESSMENT_ELEM_NAME element, + * and in the efficiency statement (Home/Evidences of achievement) after he logins on the cluster node 2 + * + * @author Lavinia Dumitrescu + * + */ +public class BulkAssessmentTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private final String COURSE_NAME_PREFIX = "AssessmentTool_selenium"; + private final String COURSE_NAME = COURSE_NAME_PREFIX + System.currentTimeMillis(); + private final String GROUP_NAME = "Gruppe 1"; + private final String ASSESSMENT_ELEM_NAME = "Bewertung 1"; + + private String STUDENT1 = "test"; + + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + //private final String STUDENT2 = "selenium_student2"; + //private final String STUDENT3 = "selenium_student3"; + private final String STUDENT2 = "seleniumstudent2"; + private final String STUDENT3 = "seleniumstudent3"; + + + /** + * Steps: <br/> + * 1. import course (AssessmentTool) and much more see <code>OlatServerSetupHelper.importCourse</code> <br/> + * 2. adds author as owner of the course <br/> + * 3. adds author as tutor of the group <br/> + * 4. creates students and let the enroll in group <br/> + * + */ + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //author adds participants to group or student enrolls in group + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + OlatLoginInfos olatLoginInfos1 = context.getStandardStudentOlatLoginInfos(1); + STUDENT1 = olatLoginInfos1.getUsername(); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos olatLoginInfos2 = context.createuserIfNotExists(1, STUDENT2, standardPassword, true, false, false, false, false); + + OlatLoginInfos olatLoginInfos3 = context.createuserIfNotExists(1, STUDENT3, standardPassword, true, false, false, false, false); + + //cleanup first - for the selenium load + /*OlatServerSetupHelper.deleteEvidencesOfAchievement(COURSE_NAME_PREFIX, olatLoginInfos1); + OlatServerSetupHelper.deleteEvidencesOfAchievement(COURSE_NAME_PREFIX, olatLoginInfos2); + OlatServerSetupHelper.deleteEvidencesOfAchievement(COURSE_NAME_PREFIX, olatLoginInfos3); + OlatServerSetupHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX);*/ + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds author as owner of the COURSE_NAME + WorkflowHelper.addOwnerToLearningResource(context.getStandardAuthorOlatLoginInfos(1).getUsername(),COURSE_NAME); + + //add author as tutor of the group + WorkflowHelper.addTutorToGroup(context.getStandardAuthorOlatLoginInfos(1).getUsername(), COURSE_NAME, GROUP_NAME); + + enrollInGroupAfterLogin(olatLoginInfos1, COURSE_NAME, GROUP_NAME); + + enrollInGroupAfterLogin(olatLoginInfos2, COURSE_NAME, GROUP_NAME); + + enrollInGroupAfterLogin(olatLoginInfos3, COURSE_NAME, GROUP_NAME); + } + + private void enrollInGroupAfterLogin(OlatLoginInfos olatLoginInfos, String courseName, String groupName) { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(olatLoginInfos); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(courseName); + EnrolmentRun enrolmentElement = courseRun.selectEnrolment(CourseEditor.ENROLMENT_TITLE); + if(!enrolmentElement.alreadyEnrolled(groupName)) { + enrolmentElement.enrol(groupName); + assertTrue(enrolmentElement.isTextPresent("You have already enroled for the learning group mentioned below")); + } + workflow.logout(); + } + + + public void testScoreBulkAssessment() throws Exception { + Context context = Context.getContext(); + //author - owner of the COURSE_NAME + OLATWorkflowHelper workflow_A = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseRun courseRun_A = workflow_A.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + AssessmentTool assessmentTool = courseRun_A.getAssessmentTool(); + Map<String,Integer> userScoreMap = new HashMap<String,Integer>(); + userScoreMap.put(STUDENT1, 2); + userScoreMap.put(STUDENT2, 3); + userScoreMap.put(STUDENT3, 4); + assessmentTool.bulkAssessment(ASSESSMENT_ELEM_NAME, userScoreMap); + workflow_A.logout(); + + //STUDENT2 check his score and efficiency statement after he logins on the cluster node 2 + String standardPassword = context.getStandardStudentOlatLoginInfos(2).getPassword(); + OlatLoginInfos olatLoginInfos2 = context.createuserIfNotExists(2, STUDENT2, standardPassword, true, false, false, false, false); + OLATWorkflowHelper workflow_2 = context.getOLATWorkflowHelper(olatLoginInfos2); + CourseRun courseRun_2 = workflow_2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + courseRun_2.selectCourseElement("Struktur 1"); + AssessmentElement assessmentElement = courseRun_2.selectAssessmentElement(ASSESSMENT_ELEM_NAME); ; + // check your score - it should be 3.000 after select element in course + assertEquals("3.000", assessmentElement.getScore()); + EvidencesOfAchievement evidencesOfAchievement = workflow_2.getHome().getEvidencesOfAchievement(); + evidencesOfAchievement.selectDetails(COURSE_NAME); + String score = evidencesOfAchievement.getCourseElementScore(ASSESSMENT_ELEM_NAME); + // check score in table + assertEquals("3.000", score); + + } + + + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/GroupDependentAssessmentTest.java b/src/test/java/org/olat/test/functional/course/assessment/GroupDependentAssessmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dd1f3da81ebc42274c7acd7208293d89d35747b0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/GroupDependentAssessmentTest.java @@ -0,0 +1,182 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.functional.course.assessment; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.AssessmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.home.EvidencesOfAchievement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * Assessment course element test. + * <br/> + * + * Test case: + * The test proves that the tutor of group1 has access to grading the newly inserted element, which is only accessible for group2. + * <br/> + * Administrator adds new Assessment course element in course and configures it. (min, max score, passed cut value, etc.) + * and allows visibility/access only to the GROUP_NAME_2. + * Course gets published. + * <br/> + * Tutor of group1 assesses student - participant of group 1 - for the latest introduced course element. + * <br/> + * Student checks the score/passed info in "Evidence of achievement" even if he does't have access to that element + * in course run. + * + * @author Lavinia Dumitrescu + * + */ +public class GroupDependentAssessmentTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private final String COURSE_NAME = "AssessmentTool_selenium" +System.currentTimeMillis(); + private final String GROUP_NAME_1 = "Gruppe 1"; + private final String GROUP_NAME_2 = "Gruppe 2"; + private final String ASSESSMENT_ELEMENT_TITLE = "Assessment_NEW"; + + private String STUDENT1 = "test"; + + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + /*private final String STUDENT2 = "selenium_student2"; + private final String TUTOR = "selenium_tutor";*/ + private final String STUDENT2 = "seleniumstudent2"; + private final String TUTOR = "seleniumtutor"; + + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //author adds participants to group or student enrolls in group + // STUDENT enrolls - login and enroll if not already member in GROUP_NAME + OlatLoginInfos olatLoginInfos1 = context.getStandardStudentOlatLoginInfos(1); + STUDENT1 = olatLoginInfos1.getUsername(); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos olatLoginInfos2 = context.createuserIfNotExists(1, STUDENT2, standardPassword, true, false, false, false, false); + + //cleanup first - only if the course name is reused + /*OlatServerSetupHelper.deleteEvidenceOfAchievement(COURSE_NAME, olatLoginInfos1); + OlatServerSetupHelper.deleteEvidenceOfAchievement(COURSE_NAME, olatLoginInfos2); + OlatServerSetupHelper.deleteAllCoursesNamed(COURSE_NAME);*/ + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //add tutor to the group: GROUP_NAME_1 + WorkflowHelper.addTutorToGroup(context.getStandardAuthorOlatLoginInfos(1).getUsername(), COURSE_NAME, GROUP_NAME_1); + //add tutor to the group: GROUP_NAME_2 + OlatLoginInfos olatLoginInfos0 = context.createuserIfNotExists(1, TUTOR, standardPassword, true, false, false, true, false); + WorkflowHelper.addTutorToGroup(olatLoginInfos0.getUsername(), COURSE_NAME, GROUP_NAME_2); + + enrollInGroupAfterLogin(olatLoginInfos1, COURSE_NAME, GROUP_NAME_1); + + enrollInGroupAfterLogin(olatLoginInfos2, COURSE_NAME, GROUP_NAME_2); + } + + private void enrollInGroupAfterLogin(OlatLoginInfos olatLoginInfos, String courseName, String groupName) { + Selenium selenium_ = Context.getContext().createSeleniumAndLogin(olatLoginInfos); + WorkflowHelper.openCourseAfterLogin(selenium_, courseName); + selenium_.click("ui=course::menu_courseNode(titleOfNode=Enrolment)"); + selenium_.waitForPageToLoad("30000"); + boolean alreadyEnrolled = seleniumEquals("enrolled", selenium_.getText("ui=course::content_enrollment_enrolledOrNot(nameOfGroup=" + groupName + ")")); + if(!alreadyEnrolled) { + selenium_.click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=" + groupName + ")"); + selenium_.waitForPageToLoad("30000"); + assertTrue(selenium_.isTextPresent("You have already enroled for the learning group mentioned below")); + } + selenium_.click("ui=tabs::logOut()"); + selenium_.waitForPageToLoad("30000"); + } + + + public void testGroupDependentAssessment() throws Exception { + Context context = Context.getContext(); + + //administrator - owner of the COURSE_NAME + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + CourseEditor courseEditor = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + //administrator configures the assessment element + AssessmentEditor assessmentEditor = (AssessmentEditor)courseEditor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, ASSESSMENT_ELEMENT_TITLE); + assessmentEditor.configure(Boolean.TRUE, 1, 10, Boolean.TRUE, 5); + //change visibility - only visible for GROUP_NAME_2 + assessmentEditor.changeVisibilityDependingOnGroup(GROUP_NAME_2); + assessmentEditor.changeAccessyDependingOnGroup(GROUP_NAME_2); + courseEditor.publishCourse(); + courseEditor.closeToCourseRun(); + + + //author - tutor of GROUP_NAME_1 + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + AssessmentTool assessmentTool = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getAssessmentTool(); + AssessmentForm assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE); + //check values for min/max score, passed cut value + assertEquals("1.0", assessmentForm.getMinScore()); + assertEquals("10.0", assessmentForm.getMaxScore()); + assertEquals("5.0", assessmentForm.getPassedCutScore()); + assessmentForm.setScore(7); + assessmentTool = assessmentForm.save(); + //check values in the assessment table (score, passed) + assertEquals("7.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + assertEquals("Passed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + //tutor changes score to 4 + assessmentForm = assessmentTool.getAssessmentFormAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE); + assessmentForm.setScore(4); + assessmentForm.save(); + //check values in the assessment table (score, passed) + assertEquals("4.000", assessmentTool.getScoreInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + assertEquals("Failed", assessmentTool.getPassedStatusInTableAsPerUser(STUDENT1, ASSESSMENT_ELEMENT_TITLE, false)); + + + //student check the "Evidence of achievement" + OLATWorkflowHelper workflow3 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun = workflow3.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + //ASSESSMENT_ELEMENT_TITLE not visible/accessible + assertFalse(courseRun.isTextPresent(ASSESSMENT_ELEMENT_TITLE)); + //but ASSESSMENT_ELEMENT_TITLE present in "Evidence of achievement" + EvidencesOfAchievement evidencesOfAchievement = workflow3.getHome().getEvidencesOfAchievement(); + evidencesOfAchievement.selectDetails(COURSE_NAME); + //check score in table + assertEquals("4.000", evidencesOfAchievement.getCourseElementScore(ASSESSMENT_ELEMENT_TITLE)); + assertEquals("Failed", evidencesOfAchievement.getCoursePassedStatus(ASSESSMENT_ELEMENT_TITLE)); + + } + + +} diff --git a/src/test/java/org/olat/test/functional/course/assessment/package.html b/src/test/java/org/olat/test/functional/course/assessment/package.html new file mode 100644 index 0000000000000000000000000000000000000000..97ab2f808b01ed2070777295427bdd019a63042e --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/assessment/package.html @@ -0,0 +1,36 @@ +<html> +<head> +</head> + +<body> + +Assessment functionality tests. <br/> +Functional tests, no codepoints, 2-node cluster setup.<br/> +All tests need a special course imported in the tests setup. + +<table border="1"> +<tbody> +<tr valign="top"> +<td>AssessmentElementTest</td><td>Tests the assessment course element, assessment tool and the evidence of achievement. + <br/> + Test case: <br/> + 1. author adds new Assessment course element in course and configures it. (min, max score, passed cut value, etc.) <br/> + 2. publish course <br/> + 3. author checks in the assessment tool the stored values for the assessment form: min/max score, passed cut value <br/> + 4. author grants score to student, and checks if the passed is correctly computed <br/> + 5. Student checks the score/passed info in the "Evidence of achievement". <br/></td> +</tr> +<tr valign="top"> +<td>BulkAssessmentTest</td><td>Test case: <br/> + Tutor (node 1) opens the AssessmentTool of the COURSE_NAME, starts the bulk assessment wizard and + adds score values for a ASSESSMENT_ELEM_NAME course element for 3 users enrolled into the group. + The scores are: 2, 3, and 4 for STUDENT1, STUDENT2, STUDENT3. + <br/> + STUDENT2 asserts his score in course run (COURSE_NAME) for the ASSESSMENT_ELEM_NAME element, + and in the efficiency statement (Home/Evidences of achievement) after he logins on the cluster node 2</td> +</tr> +</tbody> +</table> + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/course/chat/ChatTest.java b/src/test/java/org/olat/test/functional/course/chat/ChatTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f4230835e43bf13e5afc9d448c771d0647011f5c --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/chat/ChatTest.java @@ -0,0 +1,211 @@ +package org.olat.test.functional.course.chat; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.components.ChatComponent; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.group.Group; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Chattest.<br/> + * <br/> + * <p> + * Test setup:<br/> + * 1. Import a course with a test (Course_with_all_bb.zip should have a test)<br/> + * 2. Add participants seleniumauthor and seleniumstudent to the learning_group in course <br/> + * 3. Create a project group with the same members, and select chat as group tool<br/> + * 4. Login with seleniumauthor in browser 1 <br/> + * 5. Login with seleniumstudent in browser 2 <br/> + * 6. cleanup: delete course and project group<br/> + * <br/> + * Test case: <br/> + * 1. Login with seleniumstudent in browser 2 <br/> + * 2. Login with seleniumauthor in browser 1 <br/> + * 3. Seleniumauthor clicks link "(xy People are online)" <br/> + * 4. Seleniumauthor searches for user seleniumstudent <br/> + * 5. Seleniumauthor clicks username: seleniumstudent to open chat <br/> + * 6. Seleniumauthor writes "hello" and clicks send <br/> + * 7. Check whether "[TIME] seleniumauthor: hello" is displayed in browser 1 <br/> + * 8. Check whether "[TIME] seleniumauthor: hello" is displayed in browser 2 <br/> + * 9. Seleniumstudent writes "hello back" <br/> + * 10. Check whether "[TIME] seleniumstudent: hello back" is displayed in browser 2 <br/> + * 11. Check whether "[TIME] seleniumstudent: hello back" is displayed in browser 1 <br/> + * 12. Seleniumauthor logs out <br/> + * (13. Check whether "[TIME] seleniumstudent: [hat sich ausgeloggt]" is displayed in browser 1) -> removed + * 14. Seleniumauthor logs back in. + * 15. Seleniumstudent goes to course and opens course chat <br/> + * 16. Seleniumauthor goes to the same course and opens cours chat <br/> + * 17. Both go to tab group, click on group "Chatgroup", click on "Chat" in the menu, and on "enter group chat"<br/> + * 18. Both write a message "hello". + * 19. Assert that memberlist is updated so that both seleniumauthor and seleniumstudent are listed<br/> + * 20. Close group tab in browser 1 by seleniumauthor, assert that groupchat window is closed<br/> + * 21. Assert that seleniumauthor is removed in the list of the groupchatwindow in browser 2<br/> + * 22. Seleniumstudent closes all Chatwindows <br/> + * 23. Seleniumstudent enters a test <br/> + * 24. Assert that chatstatus is set to "do not disturb" during test<br/> + * 25. Assert that chat cannot be opened during test<br/> + * 26. finish test and reopen all chatwindows. Assert that conversationhistory with buddy remains.<br/> + * 27. quit course <br/> + * 28. seleniumauthor deletes course<br/> + * 29. logout seleniumauthor<br/> + * 30. logout seleniumstudent <br/> + * </p> + * + * @author Kristina + * + */ + +public class ChatTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"; + private final String COURSE_NAME_PREFIX = "ChatTest-"; + private final String COURSE_NAME = COURSE_NAME_PREFIX+System.currentTimeMillis(); + private final String CHAT_GROUP = "Chatgroup"; + private final String SELENIUM_STUDENT_FULLNAME = "Selenium Test-Student";//"selenium student"; + private final String SELENIUM_AUTHOR_FULLNAME = "Selenium Test-Author";//"selenium author"; + private final String MESSAGE1 = "hello"; + private final String MESSAGE2 = "hi there"; + private final String MESSAGE3 = "how are you"; + private final String MESSAGE4 = "terrific"; + //private final String LOGOUT_MESSAGE = "[hat sich ausgeloggt]"; //SHOULD BE ENGLISH + + private String studentUsername; + private String authorUsername; + + @Override + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + studentUsername = context.getStandardStudentOlatLoginInfos(1).getUsername(); + authorUsername = context.getStandardAuthorOlatLoginInfos(1).getUsername(); + + //cleanup first + WorkflowHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX); + + //import course + File file = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + WorkflowHelper.importCourse(file, COURSE_NAME, COURSE_NAME_PREFIX); + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun = workflow.getLearningResources().searchAndShowMyCourseContent(COURSE_NAME); + + //admin adds author and student as participants to a leaning group in the imported course + GroupManagement groupManagement = courseRun.getGroupManagement(); + GroupAdmin groupAdmin = groupManagement.createLearningGroup("blabla_gr", "bla", -1, false, false); + + String[] participants = {studentUsername, authorUsername}; + groupAdmin.addMembers(participants, new String[0]); + + // admin creates a project group, configures chat as tool, add same members + Groups groups = workflow.getGroups(); + if(groups.hasGroup(CHAT_GROUP)) { + groups.deleteGroup(CHAT_GROUP); + } + GroupAdmin groupAdmin2 = groups.createProjectGroup(CHAT_GROUP, "group for chat testing"); + groupAdmin2.setTools(false, false, false, false, false, false, true); + groupAdmin2.addMembers(participants, new String[0]); + + workflow.logout(); + } + + + public void testChatTest() throws Exception { + Context context = Context.getContext(); + + OLATWorkflowHelper author = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + OLATWorkflowHelper student = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + + ChatComponent authorChatComponent = author.getChatComponent(); + authorChatComponent.openBuddyChat(SELENIUM_STUDENT_FULLNAME); + + ChatComponent studentChatComponent = student.getChatComponent(); + studentChatComponent.openBuddyChat(SELENIUM_AUTHOR_FULLNAME); + + authorChatComponent.sendBuddyMessage(MESSAGE1); + + Thread.sleep(3000); + assertTrue(studentChatComponent.isTextPresent(authorUsername+": "+MESSAGE1)); + assertTrue(authorChatComponent.isTextPresent(authorUsername+": "+MESSAGE1)); + + studentChatComponent.sendBuddyMessage(MESSAGE2); + Thread.sleep(3000); + assertTrue(studentChatComponent.isTextPresent(studentUsername+": "+MESSAGE2)); + assertTrue(authorChatComponent.isTextPresent(studentUsername+": "+MESSAGE2)); + + student.logout(); + //Thread.sleep(3000); + //assertTrue(authorChatComponent.isTextPresent(studentUsername+": "+LOGOUT_MESSAGE)); + + //student logins back + student = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRunStudent = student.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + ChatComponent courseChatWindowStudent = courseRunStudent.getChatComponent(); + courseChatWindowStudent.openChat(false); + + CourseRun courseRunAuthor = author.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + Thread.sleep(9000); + courseRunAuthor.getChatComponent().openChat(false); + + + //project group chat + Groups groups = student.getGroups(); + Group chatGroupStudent = groups.selectGroup(CHAT_GROUP); + ChatComponent groupChatWindowStudent = chatGroupStudent.selectChat(); + Thread.sleep(9000); + groupChatWindowStudent.openProjectGoupChat(); + groupChatWindowStudent.sendMessage(MESSAGE3,"Chatroom: "+CHAT_GROUP); + + Group chatGroupAuthor = author.getGroups().selectGroup(CHAT_GROUP); + ChatComponent groupChatWindowAuthor = chatGroupAuthor.selectChat(); + Thread.sleep(9000); + groupChatWindowAuthor.openProjectGoupChat(); + groupChatWindowAuthor.sendMessage(MESSAGE4,"Chatroom: "+CHAT_GROUP); + Thread.sleep(5000); + + assertTrue(groupChatWindowStudent.isTextPresent(studentUsername+": "+MESSAGE3)); + assertTrue(groupChatWindowStudent.isTextPresent(authorUsername+": "+MESSAGE4)); + + //close project group tab + chatGroupAuthor.close(CHAT_GROUP); //20. + assertFalse(groupChatWindowAuthor.isOpen("Chatroom: "+CHAT_GROUP)); + + courseChatWindowStudent.closeExtWindow(); + + //Assert that seleniumauthor is removed in the list of the groupchatwindow in browser 2<br/> + assertFalse(groupChatWindowStudent.hasParticipant(authorUsername, "Chatroom: "+CHAT_GROUP)); + + //student closes all chat windows + groupChatWindowStudent.closeExtWindow(); + + chatGroupStudent.close(CHAT_GROUP); + + courseRunStudent.selectCourseTab(COURSE_NAME); + TestElement testElement = courseRunStudent.selectTest(CourseEditor.TEST_TITLE); + TestRun testrun = testElement.startTest(); + + ChatComponent studentChatComponent3 = courseRunStudent.getChatComponent(); + assertFalse(studentChatComponent3.isOpenStatusChangerAvailable()); + assertFalse(studentChatComponent3.isCourseChatAvailable()); + + testrun.finishTest(false, 0); + + ChatComponent finalChatComponent = student.getChatComponent(); + finalChatComponent.openBuddyChat(SELENIUM_AUTHOR_FULLNAME); + finalChatComponent.isTextPresent(MESSAGE1); + + author.logout(); + student.logout(); + } +} \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/course/chat/CourseGroupChatAndPollingTest.java b/src/test/java/org/olat/test/functional/course/chat/CourseGroupChatAndPollingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b61c51019d5d75cea123543cfc398bf008db7ffb --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/chat/CourseGroupChatAndPollingTest.java @@ -0,0 +1,80 @@ +package org.olat.test.functional.course.chat; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.components.ChatComponent; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * test groupChat stuff and polling (changing interval) + * + * @author Guido + * + */ +public class CourseGroupChatAndPollingTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = Context.DEMO_COURSE_NAME_1; + + + public void testCourseChat() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // login first + OLATWorkflowHelper workflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + LearningResources learningResources = workflowAdmin.getLearningResources(); + + for (int i = 0; i < 10; i++) { + System.out.println("run: "+i); + sendMessagesInCourseChat(learningResources, i); + } + + workflowAdmin.logout(); + } + + /** + * Open course, open chat, send messages, close chat, close course. + * @param learningResources + * @param run + * @throws InterruptedException + */ + private void sendMessagesInCourseChat(LearningResources learningResources, int run) throws InterruptedException { + CourseRun courseRun = learningResources.searchAndShowCourseContent(COURSE_NAME); + Thread.sleep(16000);//wait until course chat link is save (no reload warning) + + ChatComponent chatComponent = courseRun.getChatComponent(); + chatComponent.openStatusChanger(); + chatComponent.closeExtWindow(); + Thread.sleep(2000); + + chatComponent.openChat(true); + Thread.sleep(3000); + + String username = Context.getContext().getStandardAdminOlatLoginInfos(1).getUsername(); + if (!chatComponent.isTextPresent("("+ username +")")) { + Thread.sleep(6000); //wait for another 6s + } + assertTrue("Run number: "+run, chatComponent.isTextPresent("("+username+")")); + String msg = Long.valueOf(System.currentTimeMillis()).toString(); + + chatComponent.sendMessage(msg); + Thread.sleep(3000); //after 3s it should be here + + assertTrue("Run number: "+run+"Didn't find message as expected: "+msg, chatComponent.isTextPresent(msg)); + chatComponent.toggleAnonymous(); + Thread.sleep(3000); //after 3s it should be here + + msg = Long.valueOf(System.currentTimeMillis()).toString(); + chatComponent.sendMessage(msg); + Thread.sleep(3000); //after 3s it should be here + assertTrue("Run number: "+run+"Didn't find message: "+msg, chatComponent.isTextPresent(msg)); + + chatComponent.closeExtWindow(); + courseRun.close(COURSE_NAME); + Thread.sleep(3000); + + } + +} diff --git a/src/test/java/org/olat/test/functional/course/run/AccessVisibilityTest.java b/src/test/java/org/olat/test/functional/course/run/AccessVisibilityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..277f24dd66e1fd02529fba6b4415b98b3ac81ac1 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/AccessVisibilityTest.java @@ -0,0 +1,151 @@ +package org.olat.test.functional.course.run; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests course elements with access and visibility restrictions. + * <br/> + * Test setup: <br/> + * 1. Delete all learning resources of author. <br/> + * 2. Create student acvistudi03. + * <p> + * Test case: <br/> + * 1. Author creates wiki WIKI_NAME. <br/> + * 2. Authors creates course COURSE_NAME and adds building blocks folder, forum, wiki and assessment. <br/> + * 3. Author adds WIKI_NAME to building block wiki. <br/> + * 4. Author opens group management, creates group lg av 1 and adds standard student to group. <br/> + * 5. Author goes back to course editor and restricts visibility of forum to above created group. <br/> + * 6. Author restricts access of assessment to above created group. <br/> + * 7. Author configures visibility of wiki depending on the above assessment. <br/> + * 8. Author publishes course and switches to course run. <br/> + * 9. Student opens course, sets bookmark, checks if 3 out of 4 course elements are visible. <br/> + * 10. Student acvistudi03 opens course, only sees assessment, but cannot access it (check message). <br/> + * 11. Author opens assessment tool and sets student's assessment to "passed" . <br/> + * 12. Student can now see wiki. <br/> + * 13. Author deletes course and wiki. <br/> + * + * @author sandra + * + */ + + +public class AccessVisibilityTest extends BaseSeleneseTestCase { + + + private final String COURSE_NAME = "Access_Visibility-"+System.currentTimeMillis(); + private final String WIKI_NAME = "av_wiki"; + private boolean resourceCreated; + + + public void testAccessVisibility() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(1, "acvistudi03", standardPassword, true, false, false, false, false); + + // author01 creates wiki and course + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources1 = olatWorkflow1.getLearningResources(); + LRDetailedView lRDetailedView1 = learningResources1.createResource(WIKI_NAME, "course run test", LR_Types.WIKI); + //select again the learningResources1 + learningResources1 = olatWorkflow1.getLearningResources(); + CourseEditor courseEditor1 = learningResources1.createCourseAndStartEditing(COURSE_NAME, "course run test"); + resourceCreated = true; + courseEditor1.insertCourseElement(CourseElemTypes.FOLDER, true, null); + courseEditor1.insertCourseElement(CourseElemTypes.FORUM, true, null); + courseEditor1.insertCourseElement(CourseElemTypes.WIKI, true, null); + courseEditor1.insertCourseElement(CourseElemTypes.ASSESSMENT, true, null); + courseEditor1.selectCourseElement("Wiki"); + courseEditor1.chooseMyWikiForElement("Wiki",WIKI_NAME); + lRDetailedView1 = courseEditor1.closeToLRDetailedView(); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + courseRun1.getGroupManagement().createGroupAndAddMembers("lg av 1", null, context.getStandardStudentOlatLoginInfos(1).getUsername()); + CourseEditor courseEditor = courseRun1.getCourseEditor(); + CourseElementEditor courseElementEditor = courseEditor.selectCourseElement("Forum"); + courseElementEditor.changeVisibilityDependingOnGroup("lg av 1"); + + courseElementEditor = courseEditor.selectCourseElement("Folder"); + courseElementEditor.changeVisibilityDependingOnGroup("lg av 1"); + + courseElementEditor = courseEditor.selectCourseElement("Assessment"); + courseElementEditor.changeAccessyDependingOnGroup("lg av 1"); + courseElementEditor.editVisibilityInfo("this assessment is only accessible to learning group members"); + + courseElementEditor = courseEditor.selectCourseElement("Wiki"); + courseElementEditor.changeVisibilityDependingOnAssessment("Assessment*"); + courseEditor.publishCourse(); + courseRun1 = courseEditor.closeToCourseRun(); + + + // student01 opens course, sets bookmark, checks if 3 out of 4 elements are visible + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + LearningResources learningResources2 = olatWorkflow2.getLearningResources(); + CourseRun courseRun2 = learningResources2.searchAndShowCourseContent(COURSE_NAME); + courseRun2.setBookmark(); + + assertTrue(courseRun2.isTextPresent("Folder")); + assertTrue(courseRun2.isTextPresent("Forum")); + assertTrue(courseRun2.isTextPresent("Assessment")); + assertFalse(courseRun2.isTextPresent("Wiki")); + + // student02 opens course and only sees assessment, but cannot access it (check message) + OLATWorkflowHelper olatWorkflow3 = context.getOLATWorkflowHelper(student02); + LearningResources learningResources3 = olatWorkflow3.getLearningResources(); + CourseRun courseRun3 = learningResources3.searchAndShowCourseContent(COURSE_NAME); + + assertFalse(courseRun3.isTextPresent("Folder")); + assertFalse(courseRun3.isTextPresent("Forum")); + assertFalse(courseRun3.isTextPresent("Wiki")); + courseRun3.selectCourseElement("Assessment"); + assertTrue(courseRun3.isTextPresent("this assessment is only accessible to learning group members")); + + + // author01 opens assessment tool and sets student01's assessment to "passed" + AssessmentForm assessmentForm = courseRun1.getAssessmentTool().getAssessmentFormAsPerUser(context.getStandardStudentOlatLoginInfos(1).getUsername(), "Assessment"); + assessmentForm.setPassed(true); + assessmentForm.save(); + olatWorkflow1.logout(); + + //student01 can now see wiki + courseRun2.selectRoot(COURSE_NAME); + assertTrue(courseRun2.isTextPresent("Wiki")); + } + + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + if(resourceCreated) { + //author01 deletes course and wiki + OLATWorkflowHelper olatWorkflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources = olatWorkflow1.getLearningResources(); + LRDetailedView lRDetailedView = learningResources.searchMyResource(COURSE_NAME); + try { + learningResources = lRDetailedView.deleteLR(); + } catch (Exception e) {} + try { + learningResources.searchMyResource(WIKI_NAME).deleteLR(); + } catch (Exception e) {} + } + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } + + +} + + + diff --git a/src/test/java/org/olat/test/functional/course/run/AssessmentToolRemoveTutorTest.java b/src/test/java/org/olat/test/functional/course/run/AssessmentToolRemoveTutorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0bd93e137e400f7fcba97915d0a727f24644f3f6 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/AssessmentToolRemoveTutorTest.java @@ -0,0 +1,174 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ + +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests granting and revoking tutoring rights for one or more groups and assessing students in such groups. + * <br/> + * <p> + * Test setup: <br/> + * Expects a special "AssessmentTool" course must be imported. + Same tutor is tutoring two groups, each group has one student. <br/> + * <p> + * import course - make sure that this is the course you need! <br/> + * "administrator" adds tutor to Gruppe 1 and 2 <br/> + * STUDENT1 enrolls - login and enroll if not already member in GROUP_NAME_1 <br/> + * STUDENT2 enrolls - login and enroll if not already member in GROUP_NAME_2 <br/> + * <p> + * Test case: <br/> + * Tutor opens assessment tool, assesses first student (member of Gruppe 1) with 3 <br/> + * second student (member of Gruppe 2) with 4 points. <br/> + * Course owner removes tutor of Gruppe 2. <br/> + * Tutor opens assessment tool, assesses first student (member of Gruppe 1) with 5 <br/> + * tutor cannot asses second student (member of Gruppe 2). <br/> + * + * + * @author Marion Weber + * + */ +public class AssessmentToolRemoveTutorTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "CourseImportCourse.zip"; + + private final String COURSE_NAME = "AssessmentToolRemoveTutor-"+System.currentTimeMillis(); + private final String GROUP_NAME_1 = "Gruppe 1"; + private final String GROUP_NAME_2 = "Gruppe 2"; + + //test actors + private final String STUDENT1 = "amtststudent01"; + private final String STUDENT2 = "amtststudent02"; + private String TUTOR; + + public void setUp() throws Exception { + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + TUTOR = context.getStandardAuthorOlatLoginInfos(1).getUsername(); + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos olatLoginInfos1 = context.createuserIfNotExists(1, STUDENT1, standardPassword, true, false, false, false, false); + OlatLoginInfos olatLoginInfos2 = context.createuserIfNotExists(1, STUDENT2, standardPassword, true, false, false, false, false); + + //import course - make sure that this is the course you need! + File f = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + WorkflowHelper.importCourse(f, COURSE_NAME, "assessment test course description"); + + //"administrator" adds tutor to Gruppe 1 and 2 + WorkflowHelper.addTutorToGroup(TUTOR, COURSE_NAME, GROUP_NAME_1); + WorkflowHelper.addTutorToGroup(TUTOR, COURSE_NAME, GROUP_NAME_2); + + // STUDENT1 enrolls - login and enroll if not already member in GROUP_NAME_1 + enrollInGroupAfterLogin(olatLoginInfos1, COURSE_NAME, GROUP_NAME_1); + + // STUDENT2 enrolls - login and enroll if not already member in GROUP_NAME_2 + enrollInGroupAfterLogin(olatLoginInfos2, COURSE_NAME, GROUP_NAME_2); + } + + /** + * STUDENT enrolls - login and enroll if not already member in groupName + * @param selenium_ + * @param courseName + * @param groupName + */ + private void enrollInGroupAfterLogin(OlatLoginInfos olatLoginInfos, String courseName, String groupName) { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(olatLoginInfos); + EnrolmentRun enrolmentRun = workflow.getLearningResources().searchAndShowCourseContent(courseName).selectEnrolment("Enrolment"); + boolean alreadyEnrolled = enrolmentRun.alreadyEnrolled(groupName); + if(!alreadyEnrolled) { + enrolmentRun.enrol(groupName); + assertTrue(enrolmentRun.isTextPresent("You have already enroled for the learning group mentioned below")); + assertTrue(enrolmentRun.alreadyEnrolled(groupName)); + } + workflow.logout(); + } + + + /** + * + * + * @throws Exception + */ + public void testRunTest() throws Exception { + step1(); + + step2(); + + step3(); + } + + + private void step1() { + //Tutor opens assessment tool, assesses first student (member of Gruppe 1) with 3 + //second student (member of Gruppe 2) with 4 points. + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + AssessmentForm assessmentForm1 = courseRun1.getAssessmentTool().getAssessmentFormAsPerUser(STUDENT1, "Test 0"); + assessmentForm1.setScore(3); + AssessmentTool assessmentTool = assessmentForm1.save(); + + AssessmentForm assessmentForm2 = assessmentTool.getAssessmentFormAsPerUser(STUDENT2, "Test 1"); + assessmentForm2.setScore(4); + courseRun1 = assessmentForm2.save().close(); + courseRun1.close(COURSE_NAME); + } + + private void step2() { + //Course owner removes tutor of Gruppe 2. + OLATWorkflowHelper workflow2 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + GroupManagement groupManagement = courseRun2.getGroupManagement(); + groupManagement.removeMemberFromGroup(TUTOR, "Gruppe 2"); + courseRun2 = groupManagement.close(); + courseRun2.close(COURSE_NAME); + } + + private void step3() { + ////Tutor opens assessment tool, assesses first student (member of Gruppe 1) with 5 + // tutor cannot asses second student (member of Gruppe 2). + OLATWorkflowHelper workflow3 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CourseRun courseRun = workflow3.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + AssessmentForm assessmentForm = courseRun.getAssessmentTool().getAssessmentFormAsPerUser(STUDENT1, "Test 0"); + assessmentForm.setScore(5); + AssessmentTool assessmentTool = assessmentForm.save(); + assessmentTool.getSelenium().click("ui=course::assessment_selectType(text=As per user)"); + assessmentTool.getSelenium().waitForPageToLoad("30000"); + assertFalse(assessmentTool.getSelenium().isTextPresent("student2")); + assessmentTool.close().close(COURSE_NAME); + } + +} diff --git a/src/test/java/org/olat/test/functional/course/run/ConcurrentEditCourseNodeTest.java b/src/test/java/org/olat/test/functional/course/run/ConcurrentEditCourseNodeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9b19a36cbc9b44df5cc70a7d96b0ef0ff9b612a5 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/ConcurrentEditCourseNodeTest.java @@ -0,0 +1,213 @@ +package org.olat.test.functional.course.run; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; + +import com.thoughtworks.selenium.SeleniumException; + +/** + * + * Wiki and forum are edited concurrently. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Author creates wiki WIKI_NAME. <br/> + * 2. Authors creates course COURSE_NAME and adds building blocks forum and wiki. <br/> + * 3. Author adds WIKI_NAME to building block wiki. <br/> + * 4. Author publishes course. <br/> + * 5. Author goes to course run, selects wiki and edits index page. <br/> + * 6. Student opens course, opens wiki, creates new page. <br/> + * 7. Author and students edit same wiki page simultaneously, check if only one of them can edit. <br/> + * 8. Student goes to version tab of wiki page. <br/> + * 9. Author edits wiki page and deletes it. <br/> + * 10. Student gets message that page was deleted. <br/> + * 11. Student navigates to forum and opens new topic. <br/> + * 12. Author opens forum and deletes topic. <br/> + * 13. Student tries to edit topic but cannot. <br/> + * 14. Author removes forum and publishes course. <br/> + * 15. Student gets message to restart course. <br/> + * + * @author sandra + * + */ + +public class ConcurrentEditCourseNodeTest extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium[] = new com.thoughtworks.selenium.Selenium[2]; + + //dynamic course name, just in case it won't be deleted at the end of the test + private final String COURSE_NAME = "concurrent edit course-" + System.currentTimeMillis(); + private final String WIKI_NAME = "concurrent edit-" + System.currentTimeMillis(); + + private CourseRun courseRun_0; + private CourseRun courseRun_1; + + + public void testConcurrentEditCourseNode() throws Exception { + Context context = Context.setupContext(getFullName(), + SetupType.TWO_NODE_CLUSTER); + + { + // author creates wiki and course with wiki and forum + OLATWorkflowHelper olatWorkflow_0 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources_0 = olatWorkflow_0.getLearningResources(); + LRDetailedView lRDetailedView = learningResources_0.createResource(WIKI_NAME, "selenium", LR_Types.WIKI); + learningResources_0 = olatWorkflow_0.getLearningResources(); + CourseEditor courseEditor_0 = learningResources_0.createCourseAndStartEditing(COURSE_NAME, "selenium"); + courseEditor_0.insertCourseElement(CourseElemTypes.FORUM, true, null); + courseEditor_0.insertCourseElement(CourseElemTypes.WIKI, true, null); + courseEditor_0.chooseWikiForElement(WIKI_NAME, context.getStandardAuthorOlatLoginInfos(1).getUsername()); + courseEditor_0.publishCourse(); + LRDetailedView lRDetailedView_0 = courseEditor_0.closeToLRDetailedView(); + courseRun_0 = lRDetailedView_0.showCourseContent(); + WikiRun wikiRun_0 = (WikiRun)courseRun_0.selectWiki("Wiki"); + wikiRun_0.editPage("Welcome"); + selenium[0] = wikiRun_0.getSelenium(); + } + + { + // student creates wiki page + OLATWorkflowHelper olatWorkflow_1 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + courseRun_1 = olatWorkflow_1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + WikiRun wikiRun_1 = courseRun_1.selectWiki("Wiki"); + wikiRun_1.createOrSearchArticle("Deleteconcurrency", "Deleteconcurrency test entry"); + wikiRun_1.selectIndex(); + selenium[1] = wikiRun_1.getSelenium(); + } + + { + //both try to edit same wiki page + selenium[0].click("ui=wiki::topNavigation_editPage()"); + selenium[1].click("ui=wiki::topNavigation_editPage()"); + //selenium[0].waitForPageToLoad("30000"); + //selenium[1].waitForPageToLoad("30000"); + + int numWinners = 0; + int numLoosers = 0; + for(int i=0; i<2; i++) { + if (selenium[i].isTextPresent("Edit:Index")) { + numWinners++; + } else if (selenium[i].isTextPresent("The page (Index) is being modified by:")) { + numLoosers++; + } else { + fail("oups..."); + } + } + assertEquals("expected only 1 editor", 1, numWinners); + assertEquals("expected only 1 who cannot edit", 1, numLoosers); + } + + { + // student goes to page deleteconcurrency version tab + selenium[1].click("ui=wiki::sideNavigation_from-a-z()"); + selenium[1].waitForPageToLoad("30000"); + selenium[1].click("ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=Deleteconcurrency)"); + selenium[1].waitForPageToLoad("30000"); + selenium[1].click("ui=wiki::topNavigation_versions()"); + selenium[1].waitForPageToLoad("30000"); + } + + { + // author deletes this page + selenium[0].click("ui=wiki::sideNavigation_from-a-z()"); + selenium[0].waitForPageToLoad("30000"); + selenium[0].click("ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=Deleteconcurrency)"); + selenium[0].waitForPageToLoad("30000"); + selenium[0].click("ui=wiki::topNavigation_editPage()"); + //selenium[0].waitForPageToLoad("30000"); + selenium[0].click("ui=wiki::edit_deletePage()"); + //selenium[0].waitForPageToLoad("30000"); + selenium[0].click("ui=dialog::Okay()"); + selenium[0].waitForPageToLoad("30000"); + } + + { + // student gets message that article has been deleted, opens forum message + selenium[1].click("ui=wiki::topNavigation_article()"); + selenium[1].waitForPageToLoad("30000"); + assertTrue(selenium[1].isTextPresent("This article has been deleted and cannot be displayed anymore.")); + + //we are still in CourseRun context so the object courseRun_1 is still valid + Forum forum1 = courseRun_1.selectForum("Forum"); + forum1.openNewTopic("test entry concurrent edit", "forum message editing"); + } + + { + // author opens forum and deletes message + Forum forum_0 = courseRun_0.selectForum("Forum"); + forum_0.deleteForumTopic("test entry concurrent edit"); + } + + { + // student tries to edit forum message + selenium[1].click("ui=course::content_forum_edit()"); + selenium[1].waitForPageToLoad("30000"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + //translation key: header.cannoteditmessage + try { if (selenium[1].isTextPresent("Post cannot be edited")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium[1].click("ui=course::menu_link(link=Forum)"); + selenium[1].waitForPageToLoad("30000"); + + } + { + // author removes forum + CourseEditor courseEditor_0 = courseRun_0.getCourseEditor(); + courseEditor_0.selectCourseElement("Forum"); + courseEditor_0.deleteCourseElement(); + courseEditor_0.publishCourse(); + courseRun_0 = courseEditor_0.closeToCourseRun(); + //courseRun_0.getDetailedView(); + } + + { + // student should get message to restart course + + // code here is required because Ajax can come at any time and do a poll resulting + // in this 'Please close this course and restart' text to show up without the user clicking anywhere + if (!selenium[1].isTextPresent("Please close this course and restart.")) { + try{ + selenium[1].click("ui=course::menu_link(link=Forum)"); + selenium[1].waitForPageToLoad("30000"); + } catch(SeleniumException se) { + if (!selenium[1].isTextPresent("Please close this course and restart.")) { + fail("Could not click link=Forum but also didn't see text saying 'Please close this course and restart.'"); + } + } + } + assertTrue(selenium[1].isTextPresent("Please close this course and restart.")); + selenium[1].click("ui=tabs::closeCourse(nameOfCourse=" + COURSE_NAME + ")"); + selenium[1].waitForPageToLoad("30000"); + } + } + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + // author deletes course and wiki + LRDetailedView lRDetailedView1 = courseRun_0.getDetailedView(); + try { + LearningResources learningResources = lRDetailedView1.deleteLR(); + LRDetailedView lRDetailedView2 = learningResources.searchMyResource(WIKI_NAME); + lRDetailedView2.deleteLR(); + } catch (Exception e) {} + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } + +} diff --git a/src/test/java/org/olat/test/functional/course/run/ConcurrentForumRepliesTest.java b/src/test/java/org/olat/test/functional/course/run/ConcurrentForumRepliesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..50ee3f49f79837442a012b307be5b66c25b36e17 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/ConcurrentForumRepliesTest.java @@ -0,0 +1,165 @@ +package org.olat.test.functional.course.run; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Five students post replies and new topics in a forum shortly one after the other. + * <br/> + * Test setup: <br/> + * 1. Create five student users STUDENT_USER_NAME_1 - STUDENT_USER_NAME_5. + * <p> + * Test case: <br/> + * 1. Author creates course COURSE_NAME and adds building block forum. <br/> + * 2. Authors opens first forum topic. <br/> + * 3. Students log in and navigate to forum. <br/> + * 4. All students reply to the same forum message. <br/> + * 5. Author checks if all replies are displayed. <br/> + * 6. All students write new topic.<br/> + * 7. Author checks if all topics are displayed. <br/> + * 8. Author deletes course. <br/> + * + * @author sandra + * + */ + +public class ConcurrentForumRepliesTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "Concurrent_Forum_Replies_" + System.currentTimeMillis(); + + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + /*private final String STUDENT_USER_NAME_1 = "forumstudi_01"; + private final String STUDENT_USER_NAME_2 = "forumstudi_02"; + private final String STUDENT_USER_NAME_3 = "forumstudi_03"; + private final String STUDENT_USER_NAME_4 = "forumstudi_04"; + private final String STUDENT_USER_NAME_5 = "forumstudi_05";*/ + private final String STUDENT_USER_NAME_1 = "forumstudi01"; + private final String STUDENT_USER_NAME_2 = "forumstudi02"; + private final String STUDENT_USER_NAME_3 = "forumstudi03"; + private final String STUDENT_USER_NAME_4 = "forumstudi04"; + private final String STUDENT_USER_NAME_5 = "forumstudi05"; + + + public void testConcurrentForumReplies() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student01= context.createuserIfNotExists(1, STUDENT_USER_NAME_1, standardPassword, true, false, false, false, false); + OlatLoginInfos student02= context.createuserIfNotExists(1, STUDENT_USER_NAME_2, standardPassword, true, false, false, false, false); + OlatLoginInfos student03= context.createuserIfNotExists(1, STUDENT_USER_NAME_3, standardPassword, true, false, false, false, false); + OlatLoginInfos student04= context.createuserIfNotExists(1, STUDENT_USER_NAME_4, standardPassword, true, false, false, false, false); + OlatLoginInfos student05= context.createuserIfNotExists(1, STUDENT_USER_NAME_5, standardPassword, true, false, false, false, false); + + + // author creates course with forum, opens welcome message topic + OLATWorkflowHelper olatWorkflow_1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor1 = olatWorkflow_1.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "selenium"); + courseEditor1.insertCourseElement(CourseElemTypes.FORUM, true, null); + courseEditor1.publishCourse(); + LRDetailedView lRDetailedView1 = courseEditor1.closeToLRDetailedView(); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + Forum forum1 = courseRun1.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum1.openNewTopic("welcome", "werdet euren senf los"); + + + // students log in and navigate to forum + CourseRun courseRun2 = openCourse(student01); + Forum forum2 = courseRun2.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum2.viewTopic("welcome"); + + CourseRun courseRun3 = openCourse(student02); + Forum forum3 = courseRun3.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum3.viewTopic("welcome"); + + CourseRun courseRun4 = openCourse(student03); + Forum forum4 = courseRun4.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum4.viewTopic("welcome"); + + CourseRun courseRun5 = openCourse(student04); + Forum forum5 = courseRun5.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum5.viewTopic("welcome"); + + CourseRun courseRun6 = openCourse(student05); + Forum forum6 = courseRun6.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum6.viewTopic("welcome"); + + + // students write forum message simultaneously + forum2.replyToCurrentMessage("moutarde\n> test concurrent message reply", true); + forum3.replyToCurrentMessage("mustard\n> test concurrent message reply", true); + forum4.replyToCurrentMessage("senape\n> test concurrent message reply", true); + forum5.replyToCurrentMessage("mostaza\n> test concurrent message reply", true); + forum6.replyToCurrentMessage("sinappi\n> test concurrent message reply", true); + + + // author checks if messages are present + forum1 = courseRun1.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum1.viewTopic("welcome"); + assertTrue(forum1.isTextPresent(STUDENT_USER_NAME_1)); + assertTrue(forum1.isTextPresent("moutarde")); + assertTrue(forum1.isTextPresent(STUDENT_USER_NAME_2)); + assertTrue(forum1.isTextPresent("mustard")); + assertTrue(forum1.isTextPresent(STUDENT_USER_NAME_3)); + assertTrue(forum1.isTextPresent("senape")); + assertTrue(forum1.isTextPresent(STUDENT_USER_NAME_4)); + assertTrue(forum1.isTextPresent("mostaza")); + assertTrue(forum1.isTextPresent(STUDENT_USER_NAME_5)); + assertTrue(forum1.isTextPresent("sinappi")); + + + // all students write new forum message + forum2 = courseRun2.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum3 = courseRun3.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum4 = courseRun4.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum5 = courseRun5.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum6 = courseRun6.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum2.clickNewTopic(); + forum3.clickNewTopic(); + forum4.clickNewTopic(); + forum5.clickNewTopic(); + forum6.clickNewTopic(); + forum2.typeInNewMessage("moutarde topic", "some more senf"); + forum3.typeInNewMessage("mustard topic", "some more senf"); + forum4.typeInNewMessage("senape topic", "some more senf"); + forum5.typeInNewMessage("mostaza topic", "some more senf"); + forum6.typeInNewMessage("sinappi topic", "some more senf"); + + + //author checks if all messages are there + forum1 = courseRun1.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + assertTrue(forum1.isTextPresent("moutarde")); + assertTrue(forum1.isTextPresent("mustard")); + assertTrue(forum1.isTextPresent("senape")); + assertTrue(forum1.isTextPresent("mostaza")); + assertTrue(forum1.isTextPresent("sinappi")); + + + //author deletes course + olatWorkflow_1.getLearningResources().searchMyResource(COURSE_NAME).deleteLR(); + + } + + /** + * Login, search course and open, select forum. + * @param student + * @return the selected forum.s + */ + private CourseRun openCourse(OlatLoginInfos student) { + OLATWorkflowHelper olatWorkflow = Context.getContext().getOLATWorkflowHelper(student); + CourseRun courseRun = olatWorkflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + return courseRun; + } + +} + + + diff --git a/src/test/java/org/olat/test/functional/course/run/CourseImportWithAllBBTest.java b/src/test/java/org/olat/test/functional/course/run/CourseImportWithAllBBTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e88f543356a9b0ed8776bc5a93358c53d6bf8d80 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/CourseImportWithAllBBTest.java @@ -0,0 +1,217 @@ +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.CannotExecuteException; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.SCORM; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * + * Tests course import with all building blocks, and asserts that all bb are visible. + * <br/> + * <p> + * Test case: <br/> + * Import course with all references <br/> + * Open course <br/> + * Check all course elements: + podcast extern, + podcast intern, + blog extern, + blog intern, + topic assignment, + email, + calender, + show preview <br/> + * Delete course and all attached resources <br/> + * + * + * @author Hans-Jšrg + */ + +public class CourseImportWithAllBBTest extends BaseSeleneseTestCase { + + private final String courseTitle = "CourseImportTestCourse-"+System.currentTimeMillis(); + + + public void testCourseImport() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + +//Import course with all references + File f = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"); + assertNotNull("Could not locate the course zip!", f); + assertTrue("file "+f.getAbsolutePath()+" not found!", f.exists()); + + WorkflowHelper.importCourse(f, courseTitle, "Whatever right?"); +//Open course + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(courseTitle); +//Check all course elements + //no more inline single page since 25.05.2010 + /*courseRun.selectCourseElement("Single page - inline"); + Thread.sleep(5000); + courseRun.getSelenium().selectFrame("//iframe[contains(@src,'first.html')]"); + assertTrue(courseRun.isTextPresent("This is the first page")); + courseRun.getSelenium().selectFrame("relative=top"); + */ + + courseRun.selectCourseElement("Single page - iframe"); + Thread.sleep(1000); + courseRun.getSelenium().selectFrame("//iframe[contains(@src,'second.html')]"); + assertTrue(courseRun.getSelenium().isTextPresent("This is the second page")); + courseRun.getSelenium().selectFrame("relative=top"); + + //courseRun = new CourseRun(courseRun.getSelenium()); + courseRun.selectCourseElement("External page"); + Thread.sleep(1000); + courseRun.getSelenium().selectFrame("//iframe[contains(@src,'http://www.google.com/')]"); + assertTrue(courseRun.getSelenium().isTextPresent("iGoogle")); + courseRun.getSelenium().selectFrame("relative=top"); + + courseRun.selectCourseElement("CP learning content"); + Thread.sleep(1000); + courseRun.getSelenium().selectFrame("//iframe[contains(@src,'/MESOSWORLD/EXDE/EINF/EINF.html')]"); + assertTrue(courseRun.getSelenium().isTextPresent("empirischen")); + courseRun.getSelenium().selectFrame("relative=top"); + + SCORM scorm = courseRun.selectSCORM("SCORM learning content"); + scorm.showSCORMLearningContent(); + Thread.sleep(1000); + scorm.getSelenium().selectFrame("//iframe[@id='scormContentFrame']"); + assertTrue(scorm.getSelenium().isTextPresent("Inland Rules")); + scorm.getSelenium().selectFrame("relative=top"); + courseRun = scorm.back(); + // Thread.sleep(3000); + Forum forum = courseRun.selectForum("Forum"); + forum.openNewTopic("Test Thread", "Yes, this is really a test"); + WikiRun wiki = courseRun.selectWiki("Wiki"); + wiki.editPage("Here is a wiki test page"); + Thread.sleep(1000); + assertTrue(wiki.getSelenium().isTextPresent("Here is a wiki test page")); + courseRun.selectCourseElement("File dialog"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Upload file")); + courseRun.selectCourseElement("Folder"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("No files or folders")); + courseRun.selectCourseElement("Assessment"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Result")); + courseRun.selectEnrolment("Enrolment").enrol("1stgroup"); + courseRun.selectCourseElement("Task"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Sample solution")); + courseRun.selectCourseElement("Test"); + Thread.sleep(1000); + //translation key: qti.form.attempts + assertTrue(courseRun.getSelenium().isTextPresent("Maximum number of attempts")); + courseRun.selectCourseElement("Self-test"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Press the start button to begin with your self-test.")); + courseRun.selectCourseElement("Questionnaire"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Press the start button to begin with your questionnaire.")); + + //podcast extern + courseRun.selectCourseElement("Podcast extern"); + Thread.sleep(1000); + //podcast intern + courseRun.selectCourseElement("Podcast intern"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Swedish Music")); + //blog extern + courseRun.selectCourseElement("Blog extern"); + Thread.sleep(1000); + //blog intern + courseRun.selectCourseElement("Blog intern"); + Thread.sleep(1000); + assertTrue(courseRun.getSelenium().isTextPresent("Lorem Ipsum")); + //topic assignment + courseRun.selectCourseElement("Topic assignment"); + Thread.sleep(1000); + //email + courseRun.selectCourseElement("E-mail"); + Thread.sleep(1000); + //calender + courseRun.selectCourseElement("Calendar"); + Thread.sleep(1000); + + //show preview + CourseEditor courseEditor = courseRun.getCourseEditor(); + courseEditor.preview(); + + Folder storageFolder = courseEditor.storageFolder(); + storageFolder.selectLink("_sharedfolder", true); + storageFolder.selectLink("second.html", false); + courseEditor = storageFolder.closeStorageFolder(); + //release locks + workflow.logout(); + + } + + + + @Override + protected void cleanUpAfterRun() { + //Delete course and all attached resources + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + LearningResources learningResources = workflow.getLearningResources(); + learningResources.searchMyResource(courseTitle).deleteLR(); + + String author = Context.getContext().getStandardAdminOlatLoginInfos(1).getUsername(); + + try { + deleteAllResources(learningResources, "fois_CSCW_de_scorm", author); + deleteAllResources(learningResources, "MESOS_EXDE_EINF", author); + deleteAllResources(learningResources, "repo_1", author); + deleteAllResources(learningResources, "repo_2", author); + deleteAllResources(learningResources, "repo_3", author); + deleteAllResources(learningResources, "test Wiki", author); + deleteAllResources(learningResources, "Glossary", author); + deleteAllResources(learningResources, "Resource folder", author); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + + /** + * Deletes all resource with input resourceTitle and author. <p> + * Fill in the search form with resourceTitle and author, search, + * select entry with resourceTitle title if any found, and delete resource + * and go back to the seach form. + * + * @param learningResources + * @param resourceTitle + * @param author + */ + private void deleteAllResources(LearningResources learningResources, String resourceTitle, String author) throws Exception { + LRDetailedView lRDetailedView = learningResources.searchResource(resourceTitle, author); + while(lRDetailedView!=null) { + try { + learningResources = lRDetailedView.deleteLR(); + } catch (CannotExecuteException e) { + break; + } + lRDetailedView = learningResources.searchResource(resourceTitle, author); + } + Thread.sleep(1000); + } + +} \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/course/run/EditAndConfigureBlogTest.java b/src/test/java/org/olat/test/functional/course/run/EditAndConfigureBlogTest.java new file mode 100644 index 0000000000000000000000000000000000000000..11a4cea5530e25dcc5146493ab60615d8140a8f5 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/EditAndConfigureBlogTest.java @@ -0,0 +1,164 @@ +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.BlogEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.BlogRun; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the Blog BB and Blog Editor. + * <br/> + * <p> + * Test setup:<br/> + * 1. import Course "Course_with_all_bb.zip" <br/> + * 2. enter title "EditBlogCourse" <br/> + * 3. enter description "Edit And Configure Blog Test Course" <br/> + * <p> + * Test case: <br/> + * 1. login as author and go to tab learning resources <br/> + * 2. start course editor <br/> + * 3. click on publish course <br/> + * 4. select "Blog intern" <br/> + * 5. click "Next" <br/> + * 6. set permission "All registered OLAT users" <br/> + * 7. click "Finish" <br/> + * 8. close editor <br/> + * 9. run course <br/> + * 10. select BB "Blog intern" <br/> + * 11. click on "Create new entry" <br/> + * 12. enter title "ABlogEntryTitle" <br/> + * 13. enter description "A Blog Entry Description" <br/> + * 14. enter content "This is my short blog posting draft" <br/> + * 15. click on save draft <br/> + * 16. assure is visible "This is only a draft." <br/> + * 17. click on "Edit entry" <br/> + * 18. enter "This is my short blog posting and i like to share it with you." <br/> + * 19. click on "Publish" <br/> + * 20. assure is not visible "This is only a draft." <br/> + * 21. click on "Comments (0)" for comment <br/> + * 22. enter comment "I really enjoyed writing this." <br/> + * 23. click save <br/> + * 24. assure visible "Comments (1)" <br/> + * 25. start course editor <br/> + * 26. select BB "Blog intern" <br/> + * 27. uncheck "Blocked for learners" from section "Present" <br/> + * 28. click save <br/> + * 29. uncheck "Blocked for learners" from section "Read and Write" <br/> + * 30. click save <br/> + * 31. click publish <br/> + * 32. select "Blog intern" <br/> + * 33. click "Next" <br/> + * 34. click "Finish" <br/> + * 35. logout as author <br/> + * + * 36. login as student and go to tab learning resources <br/> + * 38. click "Search form" <br/> + * 39. enter "EditBlogCourse" <br/> + * 40. run course <br/> + * 41. select BB "Blog intern" <br/> + * 42. click Create new entry <br/> + * 43. click on "Create new entry" <br/> + * 44. enter title "StudiBlogTitle" <br/> + * 45. enter description "A Student Blog Entry Description" <br/> + * 46. enter content "This is a student's short blog posting" <br/> + * 47. click on "Publish" <br/> + * 48. assure is visible "A Student Blog Entry Description" <br/> + * 49. close course <br/> + * 50. logout as student <br/> + * + * 51. login as author and go to tab learning resources <br/> + * 52. go to tab learning resources <br/> + * 53. click "Search form" <br/> + * 54. enter "EditBlogCourse" <br/> + * 55. click on "Detailed view" for "EditBlogCourse" <br/> + * 56. click on "Delete" <br/> + * 57. logout <br/> + * + * + * </p> + * + * @author Alberto Sanz + * + */ + +public class EditAndConfigureBlogTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"; + private final String COURSE_NAME_PREFIX = "EditAndConfigureBlog-"; + private final String COURSE_NAME = COURSE_NAME_PREFIX+System.currentTimeMillis(); + + private final String BLOG_INTERN = "Blog intern"; + private final String BLOG_ENTRY_TITLE = "ABlogEntryTitle"; + private final String BLOG_ENTRY_DESCRIPTION = "A Blog Entry Description"; + private final String BLOG_ENTRY_CONTENT1 = "This is my short blog posting draft"; + private final String BLOG_ENTRY_CONTENT2 = "This is my short blog posting and i like to share it with you."; + private final String BLOG_ENTRY_COMMENT = "I really enjoyed writing this."; + + private final String BLOG_ENTRY_STUDENT = "StudiBlogTitle"; + private final String BLOG_ENTRY_STUDENT_DESCRIPTION = "A Student Blog Entry Description"; + private final String BLOG_ENTRY_STUDENT_CONTENT = "This is a student's short blog posting"; + + + + @Override + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //cleanup first + WorkflowHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX); + + //import course + File file = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + WorkflowHelper.importCourse(file, COURSE_NAME, COURSE_NAME_PREFIX); + + //assign owner + OLATWorkflowHelper workflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflowAdmin.getLearningResources().searchMyResource(COURSE_NAME).assignOwner(context.getStandardAuthorOlatLoginInfos(1).getUsername()); + } + + + + public void testEditAndConfigureBlog() throws Exception { + Context context = Context.getContext(); + + OLATWorkflowHelper workflowAuthor = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor = workflowAuthor.getLearningResources().showCourseContent(COURSE_NAME).getCourseEditor(); + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToCourseRun(); + BlogRun blogRun = courseRun.selectBlog(BLOG_INTERN); + assertNotNull(blogRun); + blogRun.createEntry(BLOG_ENTRY_TITLE, BLOG_ENTRY_DESCRIPTION, BLOG_ENTRY_CONTENT1, false); + assertTrue(blogRun.hasDraft(BLOG_ENTRY_TITLE)); + blogRun.editEntry(BLOG_ENTRY_TITLE, null, BLOG_ENTRY_CONTENT2, true); + assertFalse(blogRun.hasDraft(BLOG_ENTRY_TITLE)); + assertTrue(blogRun.hasComments(BLOG_ENTRY_TITLE,0)); + blogRun.commentEntry(BLOG_ENTRY_TITLE, BLOG_ENTRY_COMMENT); + assertTrue(blogRun.hasComments(BLOG_ENTRY_TITLE,1)); + CourseEditor courseEditor2 = courseRun.getCourseEditor(); + BlogEditor blogEditor = (BlogEditor)courseEditor2.selectCourseElement(BLOG_INTERN); + blogEditor.changeAccessBlockedForLearners(CourseElementEditor.ACCESS_TYPE.PRESENT); + blogEditor.changeAccessBlockedForLearners(CourseElementEditor.ACCESS_TYPE.READ_AND_WRITE); + courseEditor2.publishCourse(); + workflowAuthor.logout(); + + //student + OLATWorkflowHelper workflowStudent = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + CourseRun courseRun2 = workflowStudent.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + BlogRun blogRun2 = courseRun2.selectBlog(BLOG_INTERN); + blogRun2.createEntry(BLOG_ENTRY_STUDENT, BLOG_ENTRY_STUDENT_DESCRIPTION, BLOG_ENTRY_STUDENT_CONTENT, true); + assertTrue(blogRun2.isTextPresent(BLOG_ENTRY_STUDENT_DESCRIPTION)); + workflowStudent.logout(); + + //cleanup: none, it is done in setup. We might want to have a look at this course if the test failed!!! + + } +} diff --git a/src/test/java/org/olat/test/functional/course/run/EditAndConfigurePodcastTest.java b/src/test/java/org/olat/test/functional/course/run/EditAndConfigurePodcastTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9c37d8492bd87949b40ed0c2bf6ae2e0cfe7a7e3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/EditAndConfigurePodcastTest.java @@ -0,0 +1,186 @@ +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.PodcastEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.PodcastRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the Podcast BB and Podcast Editor. Also tests issue OLAT-5767 + * <br/> + * <p> + * Test setup: <br/> + * 1. import Course "Course_with_all_bb.zip" <br/> + * 2. enter title "EditPodcastCourse" <br/> + * 3. enter description "Edit And Configure Podcast Test Course" <br/> + * <p> + * Test case: <br/> + * *--- AS AUTHOR: ---* + * login as author and go to tab learning resources <br/> + * start course editor <br/> + * click on publish course <br/> + * select "Podcast intern" <br/> + * click "Next" <br/> + * set permission "All registered OLAT users" <br/> + * click "Finish" <br/> + * close editor <br/> + * run course <br/> + * select BB "Podcast intern" <br/> + * click on "Add episode" <br/> + * enter title "First Podcast" <br/> + * enter description "A Podcast Entry Description" <br/> + * click on "Select file" <br/> + * select mp3 audio file <br/> + * assure is visible "audio" and "A Podcast Entry Description" <br/> + * click on "Edit episode" <br/> + * enter description "A modified Podcast Entry Description" <br/> + * click on "Publish" <br/> + * assure is visible "A modified Podcast Entry Description" <br/> + * click on "Comments (0)" for comment <br/> + * enter comment "I really enjoyed recording this." <br/> + * click save <br/> + * assure visible "Comments (1)" <br/> + * start course editor <br/> + * select BB "Podcast intern" <br/> + * click on access tab and uncheck "Blocked for learners" from section "Present" <br/> + * click save <br/> + * uncheck "Blocked for learners" from section "Read and Write" <br/> + * click save <br/> + * click publish <br/> + * select "Podcast intern" <br/> + * click "Next" <br/> + * click "Finish" <br/> + * close editor <br/> + * *--- AS STUDENT: ---* + * login as student and go to tab learning resources <br/> + * click "Search form" <br/> + * enter "EditPodcastCourse" <br/> + * run course <br/> + * select BB "Podcast intern" <br/> + * assure is visible "A modified Podcast Entry Description" <br/> + * click on "Add episode" + * enter title "A Studi Podcast" <br/> + * enter description "A Student Podcast Entry Description" <br/> + * select mp3 audio file <br/> + * click on "Publish" <br/> + * assure is visible "audio" and "A Student Podcast Entry Description" <br/> + * *--- CONTINUE AS AUTHOR: ---* + * select BB "Podcast intern" <br/> + * assure is visible "audio" and "A Student Podcast Entry Description" <br/> + * click on "Add episode" + * enter title "My Second Podcast" + * enter desription "Can students still read this Podcast" <br/> + * select mp3 audio file <br/> + * click on "Publish" <br/> + * assure is visible "Can students still read this Podcast" <br/> + * *--- CONTINUE AS STUDENT: ---* + * select BB "Podcast intern" <br/> + * assure is visible "Can students still read this Podcast" <br/> + * *--- CONTINUE AS AUTHOR: ---* + * go to tab learning resources <br/> + * click "Search form" <br/> + * enter "EditBlogCourse" <br/> + * click on "Detailed view" for "EditBlogCourse" <br/> + * click on "Delete" <br/> + * logout <br/> + * + * </p> + * + * @author Alberto Sanz + * + */ + +public class EditAndConfigurePodcastTest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"; + private final String COURSE_NAME_PREFIX = "EditPodcastCourse-"; + private final String COURSE_NAME = COURSE_NAME_PREFIX+System.currentTimeMillis(); + + private final String PODCAST_INTERN = "Podcast intern"; + private final String PODCAST_EPISODE_TITLE = "First Podcast"; + private final String PODCAST_EPISODE_DESCRIPTION = "A Podcast Entry Description"; + private final String PODCAST_EPISODE_DESCRIPTION_MODIFIED = "A MODIFIED Podcast Entry Description"; + private final String AUDIO_FILE_NAME = "Mp3.mp3"; + private final String EPISODE_COMMENT = "I really enjoyed recording this this."; + + private final String PODCAST_EPISODE_2_TITLE = "A Studi Podcast"; + private final String PODCAST_EPISODE_2_DESCRIPTION = "A Student Podcast Entry Description"; + + private final String PODCAST_EPISODE_3_TITLE = "My Second Podcast"; + private final String PODCAST_EPISODE_3_DESCRIPTION = "Can students still read this Podcast"; + + + + @Override + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //cleanup first + WorkflowHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX); + + //import course + File file = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + WorkflowHelper.importCourse(file, COURSE_NAME, COURSE_NAME_PREFIX); + + //assign owner + OLATWorkflowHelper workflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflowAdmin.getLearningResources().searchMyResource(COURSE_NAME).assignOwner(context.getStandardAuthorOlatLoginInfos(1).getUsername()); + } + + public void testEditAndConfigurePodcast() throws Exception { + Context context = Context.getContext(); + + //author + OLATWorkflowHelper workflowAuthor = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor = workflowAuthor.getLearningResources().showCourseContent(COURSE_NAME).getCourseEditor(); + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToCourseRun(); + PodcastRun podcastRun = courseRun.selectPodcast(PODCAST_INTERN); + + File mp3File = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + AUDIO_FILE_NAME); + String remoteFilePath = Context.getContext().provideFileRemotely(mp3File); + podcastRun.createEpisode(PODCAST_EPISODE_TITLE, PODCAST_EPISODE_DESCRIPTION, remoteFilePath); + assertTrue(podcastRun.isTextPresent("audio")); + assertTrue(podcastRun.isTextPresent(PODCAST_EPISODE_DESCRIPTION)); + podcastRun.editEpisode(PODCAST_EPISODE_TITLE, PODCAST_EPISODE_DESCRIPTION_MODIFIED, null); + assertTrue(podcastRun.isTextPresent(PODCAST_EPISODE_DESCRIPTION_MODIFIED)); + podcastRun.commentEpisode(PODCAST_EPISODE_TITLE, EPISODE_COMMENT); + assertTrue(podcastRun.hasComments(PODCAST_EPISODE_TITLE, 1)); + + CourseEditor courseEditor1 = courseRun.getCourseEditor(); + PodcastEditor podcastEditor = (PodcastEditor)courseEditor1.selectCourseElement(PODCAST_INTERN); + podcastEditor.changeAccessBlockedForLearners(CourseElementEditor.ACCESS_TYPE.PRESENT); + podcastEditor.changeAccessBlockedForLearners(CourseElementEditor.ACCESS_TYPE.READ_AND_WRITE); + courseEditor1.publishCourse(); + CourseRun courseRun1 = courseEditor1.closeToCourseRun(); + + //student + OLATWorkflowHelper workflowStudent = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun2 = workflowStudent.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + PodcastRun podcastRun2 = courseRun2.selectPodcast(PODCAST_INTERN); + assertTrue(podcastRun2.isTextPresent(PODCAST_EPISODE_DESCRIPTION_MODIFIED)); + podcastRun2.createEpisode(PODCAST_EPISODE_2_TITLE, PODCAST_EPISODE_2_DESCRIPTION, remoteFilePath); + assertTrue(podcastRun2.isTextPresent("audio")); + assertTrue(podcastRun2.isTextPresent(PODCAST_EPISODE_2_DESCRIPTION)); + + //author + PodcastRun podcastRun1 = courseRun1.selectPodcast(PODCAST_INTERN); + assertTrue(podcastRun1.isTextPresent("audio")); + assertTrue(podcastRun1.isTextPresent(PODCAST_EPISODE_2_DESCRIPTION)); + podcastRun1.createEpisode(PODCAST_EPISODE_3_TITLE, PODCAST_EPISODE_3_DESCRIPTION, remoteFilePath); + assertTrue(podcastRun1.isTextPresent(PODCAST_EPISODE_3_DESCRIPTION)); + + //student + podcastRun2 = courseRun2.selectPodcast(PODCAST_INTERN); + assertTrue(podcastRun2.isTextPresent(PODCAST_EPISODE_3_DESCRIPTION)); + } +} diff --git a/src/test/java/org/olat/test/functional/course/run/EditInfoMessageTest.java b/src/test/java/org/olat/test/functional/course/run/EditInfoMessageTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e94b0dab9d97d91c86667aeb32569b695174d085 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/EditInfoMessageTest.java @@ -0,0 +1,241 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.functional.course.run; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.InfoMessageRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 4. jan 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class EditInfoMessageTest extends BaseSeleneseTestCase { + + + private static final String COURSE_NAME = "Messages Course"; + private static final String INFO_MESSAGE_NAME = "Special messages"; + + public void setUp() throws Exception { + //each test has to setup a context + Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + } + + /** + * Login, create an empty, logout, login, go to Learning resources, select Courses, select "Messages Course", + * Show content, open Course Editor, insert a Info message course element, publish course, add messages, + * count if the messages are there, show older messages, count the messages, show current messages, count + * the messages. + * + * @throws Exception + */ + @Test + public void testNewInfoMessages() throws Exception { + //delete old courses + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + + //Get a workflow object for the default administrator user. + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + + //create to learning resources and the course named COURSE_NAME, get a CourseRun object + workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_NAME).publishCourse(); + workflow.logout(); + + //add standard author as owner + workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + workflow.getLearningResources().searchMyResource(COURSE_NAME).assignOwner(Context.getContext().getStandardAuthorOlatLoginInfos(1).getUsername()); + workflow.logout(); + + workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + + //go to the course editor + CourseEditor courseEditor = courseRun.getCourseEditor(); + + //insert a course element of type info message, with a specified title + CourseElementEditor courseElementEditor = courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.INFO_MESSAGE, true, INFO_MESSAGE_NAME); + assertTrue(courseElementEditor.isTextPresent(INFO_MESSAGE_NAME)); + + //publish course + courseEditor.publishCourse(); + + //create a message + courseRun = courseEditor.closeToCourseRun(); + InfoMessageRun infoRun = courseRun.selectInfoMessage(INFO_MESSAGE_NAME); + infoRun.createMessage("Hello 0", "Hello world 0"); + + //create 11 messages more + for(int i=1; i<12; i++) { + infoRun.createMessage("Hello " + i, "Hello world " + i); + } + + int found1 = countMessages(infoRun); + assertEquals(10, found1); + + //show and count all messages + infoRun.showOlderMessage(); + int found2 = countMessages(infoRun); + assertEquals(12, found2); + + //show and count current messages + infoRun.showCurrentMessage(); + int found3 = countMessages(infoRun); + assertEquals(10, found3); + + //edit first message + infoRun.editFirstMessage(); + assertTrue(infoRun.isMessageEdited()); + infoRun.save(); + + //delete first message + infoRun.deleteFirstMessage(); + infoRun.yes(); + infoRun.showOlderMessage(); + int found4 = countMessages(infoRun); + assertEquals(11, found4); + + //logout + workflow.logout(); + } + + /** + * Login with the standard admin and the standard author, open "Messages Course", + * open course building block "Messages", standard admin edit a message, author try to edit the same message, + * and try to delete it. The main goal of this test is to check if the lock are correctly set and released. + * @throws Exception + */ + @Test(dependsOnMethods={"testNewInfoMessages"}) + public void testConcurrentEditMessage() throws Exception { + //Get a workflow object for the default administrator. + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + InfoMessageRun infoRun1 = courseRun1.selectInfoMessage(INFO_MESSAGE_NAME); + + int found1 = countMessages(infoRun1); + assertEquals(10, found1); + + //Get a workflow object for the default author. + OLATWorkflowHelper workflow2 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + InfoMessageRun infoRun2 = courseRun2.selectInfoMessage(INFO_MESSAGE_NAME); + + int found2 = countMessages(infoRun2); + assertEquals(10, found2); + + //check the locks on the messages + + //admin edit a message + infoRun1.editFirstMessage(); + assertTrue(infoRun1.isMessageEdited()); + //author try to edit the same message + infoRun2.editFirstMessage(); + assertTrue(infoRun2.isMessageAlreadyEdited()); + infoRun2.dialogOk(); + //author try to delete the same message + infoRun2.deleteFirstMessage(); + assertTrue(infoRun2.isMessageAlreadyEdited()); + infoRun2.dialogOk(); + //admin save the edit box + infoRun1.save(); + + + //author edit a message + infoRun2.editFirstMessage(); + assertTrue(infoRun2.isMessageEdited()); + //admin try to edit + infoRun1.editFirstMessage(); + assertTrue(infoRun1.isMessageAlreadyEdited()); + infoRun1.dialogOk(); + //author close the overlay + infoRun2.close(); + + + //admin edit a message + infoRun1.editFirstMessage(); + assertTrue(infoRun1.isMessageEdited()); + //author try to edit + infoRun2.editFirstMessage(); + assertTrue(infoRun2.isMessageAlreadyEdited()); + infoRun2.dialogOk(); + //admin close the overlay + infoRun1.cancel(); + + + //author edit a message + infoRun2.editFirstMessage(); + assertTrue(infoRun2.isMessageEdited()); + infoRun2.cancel(); + + //logout + workflow1.logout(); + workflow2.logout(); + } + + /** + * Test the possibility to create, edit and delete a message with a standard student (cannot) + * and the author (can). + */ + @Test(dependsOnMethods={"testConcurrentEditMessage"}) + public void testSecurityBasics() { + //Get a workflow object for the default student. + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardStudentOlatLoginInfos(1)); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + InfoMessageRun infoRun1 = courseRun1.selectInfoMessage(INFO_MESSAGE_NAME); + + //it cannot edit or delete a message + assertFalse(infoRun1.canCreateMessage()); + assertFalse(infoRun1.canEditMessage()); + assertFalse(infoRun1.canDeleteMessage()); + + + //Get a workflow object for the default author. + OLATWorkflowHelper workflow2 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + InfoMessageRun infoRun2 = courseRun2.selectInfoMessage(INFO_MESSAGE_NAME); + + //it cannot edit or delete a message + assertTrue(infoRun2.canCreateMessage()); + assertTrue(infoRun2.canEditMessage()); + assertTrue(infoRun2.canDeleteMessage()); + } + + private int countMessages(InfoMessageRun infoRun) { + int found = 0; + for(int i=0; i<12; i++) { + if(infoRun.hasMessage("Hello " + i)) { + found++; + } + } + return found; + } +} diff --git a/src/test/java/org/olat/test/functional/course/run/UploadFilesInCourseTest.java b/src/test/java/org/olat/test/functional/course/run/UploadFilesInCourseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ce0be42d77483d77d31da49aee9db859a5b812f9 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/UploadFilesInCourseTest.java @@ -0,0 +1,142 @@ +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.SinglePageEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.FileDialog; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests file upload for Folder, SinglePage, Forum, Wiki and FileDialog. + * <br/> + * <p> + * Test setup:<br/> + * clean up before start <br/> + * Import files <br/> + * <p> + * Test case:<br/> + * Import files <br/> + * Open course <br/> + * Open editor, storage folder and delete existing html-file <br/> + * Attach deleted single page again and check in preview <br/> + * Go to forum and create a new message with two file attachments + - check if uploaded properly and delete again <br/> + * Go to wiki and upload a pdf file to be linked in the wiki + - check if there <br/> + * Delete course and all attached resources <br/> + * + * + * + * + * + * @author hjzuber + * + */ +public class UploadFilesInCourseTest extends BaseSeleneseTestCase { + + public void testUploadFiles() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + +//Import files + File course = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"); + assertNotNull("Could not locate the course zip!", course); + assertTrue("file "+course.getAbsolutePath()+" not found!", course.exists()); + String courseTitle = "CourseImportTestCourse-"+System.currentTimeMillis(); + WorkflowHelper.importCourse(course, courseTitle, "Whatever right?"); + + File html = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "first.html"); + File doc = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Word.doc"); + File docx = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Word_new.docx"); + File pdf = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Pdf.pdf"); + String remoteHtml = Context.getContext().provideFileRemotely(html); + String remoteDoc = Context.getContext().provideFileRemotely(doc); + String remoteDocx = Context.getContext().provideFileRemotely(docx); + String remotePdf = Context.getContext().provideFileRemotely(pdf); + + +//Open course + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(courseTitle); + Thread.sleep(3000); + //Open editor, storage folder and delete existing html-file + CourseEditor courseEditor = courseRun.getCourseEditor(); + Folder storageFolder = courseEditor.storageFolder(); + storageFolder.deleteItem("first.html"); + courseEditor = storageFolder.closeStorageFolder(); + //Attach deleted single page again and check in preview + //single page is always inframe since 25.05.2010 + SinglePageEditor singlePageEditor = (SinglePageEditor)courseEditor.selectCourseElement("Single page - inline"); + singlePageEditor.replacePage(SinglePageEditor.SELECT_TYPE.UPLOAD_TO_STORAGE_FOLDER, remoteHtml); + singlePageEditor.preview(); + Thread.sleep(5000); + courseRun.getSelenium().selectFrame("//iframe[contains(@src,'first.html')]"); + assertTrue(singlePageEditor.isTextPresent("This is the first page")); + courseRun.getSelenium().selectFrame("relative=top"); + singlePageEditor.closePreview(); + + //Go to forum and create a new message with two file attachments - check if uploaded properly and delete again + courseRun = courseEditor.closeToCourseRun(); + Forum forum = courseRun.selectForum("Forum"); + forum.openNewTopic("Yes we want to upload", "two Word files"); + forum.attachFileToMsg(remoteDoc); + Thread.sleep(1000); + assertTrue(forum.isTextPresent("Word.doc")); + forum.attachFileToMsg(remoteDocx); + Thread.sleep(1000); + assertTrue(forum.isTextPresent("Word_new.docx")); + forum.deleteAttachedFile("Word_new.docx"); + //Go to wiki and upload a pdf file to be linked in the wiki - check if there + WikiRun wikiRun = courseRun.selectWiki("Wiki"); + wikiRun.insertMedia(remotePdf, "Pdf.pdf"); + Thread.sleep(1000); + assertTrue(wikiRun.isTextPresent("Media:Pdf.pdf")); + + FileDialog fileDialog = courseRun.selectFileDialog("File dialog"); + fileDialog.uploadFile(remotePdf); + Thread.sleep(1000); + assertTrue(courseRun.isTextPresent("Pdf.pdf")); + fileDialog.deleteSingleFile(); + + Folder folder = courseRun.selectFolder("Folder"); + folder.uploadFile(null, remoteDoc); + assertTrue(folder.isTextPresent("Word.doc")); + + //Delete course and all attached resources + courseRun.getDetailedView().deleteLR(); + + deleteResource(workflow, "fois_CSCW_de_scorm"); + deleteResource(workflow, "MESOS_EXDE_EINF"); + + deleteResource(workflow, "repo_1"); + deleteResource(workflow, "repo_2"); + deleteResource(workflow, "repo_3"); + deleteResource(workflow, "test Wiki"); + deleteResource(workflow, "Glossary"); + deleteResource(workflow, "Resource folder"); + + } + + /** + * Deletes resource with the given name, having the administrator as author. + * Filter for the author as well, else won't work for selenium load. + * @param workflow + * @param title + */ + private void deleteResource(OLATWorkflowHelper workflow, String title) { + LRDetailedView lRDetailedView = workflow.getLearningResources().searchResource(title, Context.getContext().getStandardAdminOlatLoginInfos(1).getUsername()); + if(lRDetailedView!=null) { + lRDetailedView.deleteLR(); + } + } +} diff --git a/src/test/java/org/olat/test/functional/course/run/UseLTITest.java b/src/test/java/org/olat/test/functional/course/run/UseLTITest.java new file mode 100644 index 0000000000000000000000000000000000000000..bf8ee5ea58fa10128098508b4cbfe18b1a3b90e1 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/UseLTITest.java @@ -0,0 +1,153 @@ +package org.olat.test.functional.course.run; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.LTIPageEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.user.UserSettings; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the LTI BB: insert, configure, launch. + * <br/> + * <p> + * Test setup:<br/> + * import Course "Course_with_all_bb.zip" + * enter title "LTIUseTestCourse" + * enter description "Edit And Configure LTI Test Course" + * <p> + * Test case: <br/> + * + * ------------- as author ------------------- <br/> + * login as author and go to tab learning resources <br/> + * start course editor <br/> + * go to BB "LTI Example" <br/> + * click on tab "Page content" <br/> + * enter "URL": http://www.imsglobal.org/developers/BLTI/tool.php <br/> + * enter "Key": lmsng.school.edu <br/> + * enter "Password": secret <br/> + * uncheck "Send name to supplier" <br/> + * uncheck "Send e-mail address to supplier" <br/> + * check "Show information sent" <br/> + * click "Save" <br/> + * click "Show Preview" <br/> + * assure authors name and lastname are NOT visible <br/> + * assure authors email is NOT visible <br/> + * click on "Close Preview" <br/> + * check "Send name to supplier" <br/> + * check "Send e-mail address to supplier" <br/> + * click "Save" <br/> + * click "Show Preview" <br/> + * assure authors name and lastname are visible <br/> + * assure authors email is visible <br/> + * click on "Close Preview" <br/> + * click on "LTI page" from "Insert course elements" navigation <br/> + * insert the new LTI BB to the course tree structure <br/> + * go to new BB "LTI Page" <br/> + * click on tab "Page content" <br/> + * enter "URL": URL": http://www.imsglobal.org/developers/BLTI/tool.php <br/> + * enter "Key": lmsng.school.edu <br/> + * enter "Password": secret <br/> + * check "Show information sent" <br/> + * click "Save" <br/> + * click "Publish" from "Editor tools" <br/> + * select "LTI Example" <br/> + * select "LTI Page" <br/> + * click "Next" <br/> + * set permission "All registered OLAT users" <br/> + * click "Finish" <br/> + * close course editor <br/> + * + * --------- as student ------------- <br/> + * login as student and go to tab learning resources <br/> + * search for course with title "LTIUseTestCourse" <br/> + * run course <br/> + * click on "LTI Example" from the Course Navigation <br/> + * click "Launch Endpoint with BasicLTI Data" <br/> + * assure "Launch Endpoint with BasicLTI Data" is visible <br/> + * click on "LTI Page" from the Course Navigation <br/> + * assure "Launch Endpoint with BasicLTI Data" is visible <br/> + * close course <br/> + * </p> + * + * @author Alberto Sanz + * + */ + +public class UseLTITest extends BaseSeleneseTestCase { + + private final String IMPORTABLE_COURSE_PATH = Context.FILE_RESOURCES_PATH + "Course_with_all_bb.zip"; + private final String COURSE_NAME_PREFIX = "LTIUseTestCourse"; + private final String COURSE_NAME = COURSE_NAME_PREFIX+System.currentTimeMillis(); + //private final static String COURSE_DESCRIPTION = "Edit And Configure LTI Test Course"; + + private final static String LTI_ELEM_NAME = "LTI Example"; + private final static String URL = "http://www.imsglobal.org/developers/BLTI/tool.php"; + private final static String KEY = "lmsng.school.edu"; + private final static String PASSWORD = "secret"; + + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //cleanup first + WorkflowHelper.deleteLearningResources(context.getStandardAdminOlatLoginInfos(1).getUsername(), COURSE_NAME_PREFIX); + + //import course + File file = WorkflowHelper.locateFile(IMPORTABLE_COURSE_PATH); + WorkflowHelper.importCourse(file, COURSE_NAME, COURSE_NAME_PREFIX); + + //assign owner + OLATWorkflowHelper workflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflowAdmin.getLearningResources().searchMyResource(COURSE_NAME).assignOwner(context.getStandardAuthorOlatLoginInfos(1).getUsername()); + } + + public void testEditAndConfigureLTI() throws Exception { + Context context = Context.getContext(); + + OlatLoginInfos authorOlatLoginInfos = context.getStandardAuthorOlatLoginInfos(1); + + OLATWorkflowHelper workflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + UserSettings userSettings = workflowAdmin.getUserManagement().selectUser(authorOlatLoginInfos.getUsername()); + String authorEmail = userSettings.getEmail(); + //author + + OLATWorkflowHelper workflowAuthor = context.getOLATWorkflowHelper(authorOlatLoginInfos); + //CourseEditor courseEditor = workflowAuthor.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + //LTIPageEditor lTIPageEditor = (LTIPageEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.LTI_PAGE, true, LTI_ELEM_NAME); + CourseEditor courseEditor = workflowAuthor.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + LTIPageEditor lTIPageEditor = (LTIPageEditor)courseEditor.selectCourseElement(LTI_ELEM_NAME); + lTIPageEditor.configurePage(URL, KEY, PASSWORD, false, false, true); + LTIPageEditor.LTIPreview preview = lTIPageEditor.showPreview(); + + assertFalse(preview.hasInfo(authorEmail)); + lTIPageEditor = preview.closePreview(); + lTIPageEditor.configurePage(null, null, null, true, true, false); + + LTIPageEditor.LTIPreview preview2 = lTIPageEditor.showPreview(); + assertTrue(preview2.hasInfo(authorEmail)); + preview2.closePreview(); + + LTIPageEditor lTIPageEditor2 = (LTIPageEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.LTI_PAGE, true, null); + lTIPageEditor2.configurePage(URL, KEY, PASSWORD, false, false, true); + + courseEditor.publishCourse(); + courseEditor.closeToCourseRun(); + + //student + OLATWorkflowHelper olatWorkflowStudent = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun = olatWorkflowStudent.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + courseRun.selectLTI(LTI_ELEM_NAME).launch(); + + courseRun.selectLTI(CourseEditor.LTI_TITLE).launch(); + olatWorkflowStudent.logout(); + + } +} diff --git a/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step1.html b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step1.html new file mode 100644 index 0000000000000000000000000000000000000000..8797b35848e9f42caae202e9d2ab2d779b66b557 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step1.html @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://demo.olat.org/olat/dmz//olat/dmz//" /> +<title>TestAssessmentTest_01</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">TestAssessmentTest_01</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz//olat/dmz///olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author03</td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::password()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_assessmentTool()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectType(text=As per user)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectUser(username=student03)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectAssessmentCourseNode(title=Test 0)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::assessment_setScore()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::assessment_setScore()</td> + <td>3</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_back()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectType(text=As per user)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectUser(username=student2)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectAssessmentCourseNode(title=Test 1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::assessment_setScore()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::assessment_setScore()</td> + <td>4</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_closeAssessmentTool()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::closeCourse(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step2.html b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step2.html new file mode 100644 index 0000000000000000000000000000000000000000..c525dd9e75f5b2c29f8381558b02b56b5fa17810 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step2.html @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://demo.olat.org/olat/dmz//olat/dmz//" /> +<title>TestAssessmentTest_02</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">TestAssessmentTest_02</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz//olat/dmz///olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>admin03</td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::password()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::menu_allMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_userlist_clickUserName(nameOfUser=author03)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_userDetails_removeFromGroup(nameOfGroup=Gruppe 2)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_close()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::closeCourse(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step3.html b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step3.html new file mode 100644 index 0000000000000000000000000000000000000000..f642896cffc7b631c5b6b921e7ad2297666e4337 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/assessmentTool_RemoveTutor_step3.html @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="http://demo.olat.org/olat/dmz//olat/dmz//" /> +<title>TestAssessmentTest_03</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">TestAssessmentTest_03</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz//olat/dmz///olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author03</td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::password()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_assessmentTool()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectType(text=As per user)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectUser(username=student03)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectAssessmentCourseNode(title=Test 0)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::assessment_setScore()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::assessment_setScore()</td> + <td>3</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_back()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectType(text=As per user)</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>student2</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::assessment_closeAssessmentTool()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::closeCourse(nameOfCourse=AssessmentTool)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/run/course_run_access_visibility.html b/src/test/java/org/olat/test/functional/course/run/course_run_access_visibility.html new file mode 100644 index 0000000000000000000000000000000000000000..5dc95a4619c5de224b2dd3c78ba01d4af4fd067b --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/course_run_access_visibility.html @@ -0,0 +1,616 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>course_run_access_visibility</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">course_run_access_visibility</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/?o_winrndo=1</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_wiki()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>av_wiki</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_description()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>course run test</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_course()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>Access_Visibility</td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>course run test</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertFolder()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertForum()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertWiki()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAssessment()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::menu_link(link=Wiki)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_tabWikiLearningContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWiki()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWikiSearch_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWikiSearch_chooseWiki(nameOfWiki=av_wiki)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_learningResource_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()</td> + <td>lg av 1</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_close()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_courseEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_tabVisibility()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_dependingGroup()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_selectLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=lg av 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::menu_link(link=Folder)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_tabVisibility()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_dependingGroup()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_selectLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=lg av 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Assessment)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_access_tabAccess()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_access_dependingGroup()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_access_selectLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=lg av 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_access_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_tabVisibility()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_editInformation()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_visibility_infoField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=courseEditor::content_visibility_infoField()</td> + <td>this forum is only accessible to learning group members</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_saveInfo()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Wiki)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_tabVisibility()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_dependingAssessment()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::content_visibility_selectElement()</td> + <td>label=Assessment*</td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_visibility_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<!--now student01--> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/?o_winrndo=1</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_searchForm()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>search mask learning resources title</td> + <td>Access_Visibility</td> +</tr> +<tr> + <td>click</td> + <td>search button</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Access_Visibility)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_generalTools_setBookmark()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>Folder</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>Forum</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>Assessment</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>Wiki</td> + <td></td> +</tr> +<!--now student02--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Assessment)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>this assessment is only accessible to learning group members</td> + <td></td> +</tr> +<!--author01 in assessment tool--> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_assessmentTool()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectType(text=As per user)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectUser(username=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::assessment_selectAssessmentCourseNode(title=Assessment)</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=course::assessment_setPassed()</td> + <td>label=Yes</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<!--student01 can now see wiki--> +<tr> + <td>click</td> + <td>ui=course::menu_root(nameOfCourse=Access_Visibility)</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>Wiki</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_edit_course_nodes.html b/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_edit_course_nodes.html new file mode 100644 index 0000000000000000000000000000000000000000..26699f8b01f6bbfef4e0143e44618c1d8d0462ef --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_edit_course_nodes.html @@ -0,0 +1,487 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>course_run_concurrent_edit_course_nodes</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">course_run_concurrent_edit_course_nodes</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_wiki()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>concurrent edit</td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>selenium</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_course()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>concurrent edit course</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_description()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>selenium</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertForum()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertWiki()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_tabWikiLearningContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWiki()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWikiSearch_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbWiki_chooseWikiSearch_chooseWiki(nameOfWiki=concurrent edit)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Wiki)</td> + <td></td> +</tr> +<!--now student opens course and wiki--> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=concurrent edit course)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Wiki)</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=wiki::sideNavigation_searchInput()</td> + <td>Deleteconcurrency</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::sideNavigation_createOrSearch()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=Deleteconcurrency)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::topNavigation_editPage()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=wiki::edit_editFormTextarea()</td> + <td>Deleteconcurrency test entry</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::sideNavigation_index()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::topNavigation_editPage()</td> + <td></td> +</tr> +<!--both try to edit index wiki page--> +<!--student goes to page version tab--> +<tr> + <td>click</td> + <td>ui=wiki::sideNavigation_from a-z()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=Deleteconcurrency)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::topNavigation_versions()</td> + <td></td> +</tr> +<!--author goes to page edit tab, deletes--> +<tr> + <td>click</td> + <td>ui=wiki::topNavigation_editPage()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::edit_deletePage()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dialog::OK()</td> + <td></td> +</tr> +<!--student goes to tab article--> +<tr> + <td>clickAndWait</td> + <td>ui=wiki::topNavigation_article()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>This article has been deleted and cannot be displayed anymore.</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_newTopic()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_typeMsgTitle()</td> + <td>test entry concurrent edit</td> +</tr> +<tr> + <td>click</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td>forum message editing</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_save()</td> + <td></td> +</tr> +<!--author opens forum and deletes message--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_viewTopic(nameOfTopic=test entry concurrent edit)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_delete()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_deleteYes()</td> + <td></td> +</tr> +<!--student tries to edit forum message--> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_edit()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>You must not edit this message.</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<!--author removes forum--> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_courseEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_modifyTools_delete()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dialog::Yes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_generalTools_detailedView()</td> + <td></td> +</tr> +<!--student should get message to restart course--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Please close this course and restart.</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::closeCourse(nameOfCourse=concurrent edit course)</td> + <td></td> +</tr> +<!--author deletes course--> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_forum_replies.html b/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_forum_replies.html new file mode 100644 index 0000000000000000000000000000000000000000..55c08ae84940d85e08cf94ffb13d649d9a9fb288 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/run/course_run_concurrent_forum_replies.html @@ -0,0 +1,284 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>course_run_concurrent_forum_replies</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">course_run_concurrent_forum_replies</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_course()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>Concurrent Forum Replies</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_description()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>selenium</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertForum()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_newTopic()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_typeMsgTitle()</td> + <td>welcome</td> +</tr> +<tr> + <td>click</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td>werdet euren senf los</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_save()</td> + <td></td> +</tr> +<!--now students log in and reply to message--> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_searchForm()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::content_searchForm_titleField()</td> + <td>Concurrent Forum Replies</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_searchForm_search()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Concurrent Forum Replies)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_viewTopic(nameOfTopic=welcome)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_replyWithQuotation()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td>moutarde<br />> test concurrent message reply</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<!--author checks if all messages are present--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Forum)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_viewTopic(nameOfTopic=welcome)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>student01 - student05</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>moutarde etc.</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/course/topic/CreateAndConfigureTopicAssignmentTest.java b/src/test/java/org/olat/test/functional/course/topic/CreateAndConfigureTopicAssignmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..854657a0165f8007c9fab13a94d7ea6980d50720 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/topic/CreateAndConfigureTopicAssignmentTest.java @@ -0,0 +1,95 @@ +package org.olat.test.functional.course.topic; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.course.editor.TopicAssignmentEditor; +import org.testng.annotations.Test; + +/** + * + * Tests the new bb topic assignment. Step 1: Configuration. + * <br/> + * <p> + * Test setup:<br/> + * 1. import demo course or any other course. Copy course and rename to TOPIC_ASSIGNMENT_COURSE. <br/> + * 2. prepare following test users: 1 author (AUTHOR), 3 users without authoring rights TUTOR1, TUTOR2, TUTOR3 + * + * Testcase:<br/> + * 1. log in as AUTHOR + * 2. go to learning resources + * 3. search for TOPIC_ASSIGNMENT_COURSE from test setup + * 4. edit content of TOPIC_ASSIGNMENT_COURSE + * 5. add bb topic assignment, name it TOPIC_ASSIGNMENT_1 + * 6. go to tab configuration + * 7. limit number or project per student to 2 + * 8. check the two other dependent checkboxes, save + * 9. go to tab persons in charge + * 10. add TUTOR1, TUTOR2, TUTOR3 as topic authors + * (leave all other config options as default) + * 11. publish TOPIC_ASSIGNMENT_COURSE, set access to all registered users + * 12. log out + * </p> + * + * @author sandra + * + */ +public class CreateAndConfigureTopicAssignmentTest extends BaseSeleneseTestCase { + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_1; + + + + @Override + public void setUp() throws Exception { + System.out.println("********* CreateAndConfigureTopicAssignmentTest **************"); + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //clone DEMO_COURSE_NAME and work with the clone + //assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, TopicAssignmentSuite.COURSE_NAME)); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + + //workaround: could not copy course at the moment + workflow.getLearningResources().createCourseAndStartEditing(TopicAssignmentSuite.COURSE_NAME, TopicAssignmentSuite.COURSE_NAME).publishCourse(); + workflow.logout(); + + workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflow.getLearningResources().searchMyResource(TopicAssignmentSuite.COURSE_NAME).assignOwner(context.getStandardAuthorOlatLoginInfos(1).getUsername()); + + //create test users + OlatLoginInfos tutor1= context.createuserIfNotExists(2, TopicAssignmentSuite.TUTOR1, true, false, false, false, false); + OlatLoginInfos tutor2= context.createuserIfNotExists(1, TopicAssignmentSuite.TUTOR2, true, false, false, false, false); + OlatLoginInfos tutor3= context.createuserIfNotExists(2, TopicAssignmentSuite.TUTOR3, true, false, false, false, false); + + } + + @Test(groups={TopicAssignmentSuite.FIRST}) + public void testCreateAndConfigureTopicAssignment() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor = workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME).getCourseEditor(); + TopicAssignmentEditor topicAssignmentEditor = (TopicAssignmentEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TOPIC_ASSIGNMENT, true, TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + topicAssignmentEditor.configure(true, 2, true, true); + topicAssignmentEditor.addUser(TopicAssignmentSuite.TUTOR1); + topicAssignmentEditor.addUser(TopicAssignmentSuite.TUTOR2); + topicAssignmentEditor.addUser(TopicAssignmentSuite.TUTOR3); + + //TODO: LD: workaround for selectall problem in publishCourse, doesn't always work with only one course element, so we insert a second one. + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + courseEditor.publishCourse(); + workflow.logout(); + + } + + @Override + protected void cleanUpAfterRun() { + //nothing to cleanup - there is a follow-up test using the created resource + + } + + +} diff --git a/src/test/java/org/olat/test/functional/course/topic/CreateTopicInTopicAssignmentTest.java b/src/test/java/org/olat/test/functional/course/topic/CreateTopicInTopicAssignmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6de85b7095fdda45c926045d74c7a078257f5d81 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/topic/CreateTopicInTopicAssignmentTest.java @@ -0,0 +1,122 @@ +package org.olat.test.functional.course.topic; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TopicAssignmentRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Tests the new bb topic assignment. Step 2: Create topics + * <br/> + * <p> + * Test setup:<br/> + * 1. test created in CreateAndConfigureTopicAssignmentTest (TOPIC_ASSIGNMENT_COURSE) is available. <br/> + * 2. TUTOR1, TUTOR2, TUTOR3 from CreateAndConfigureTopicAssignmentTest are available + * + * Testcase:<br/> + * 1. log in as TUTOR1 + * 2. go to learning resources, search form + * 3. search for TOPIC_ASSIGNMENT_COURSE and open course run + * 4. go to bb TOPIC_ASSIGNMENT_1 + * 5. check if the button "create topic" is available + * 6. check if text "No Topics for this Topic assignment available." is present + * 7. click "create topic" + * 8. title: "Topic_Tutor1", description "Description Topic of Tutor 1" + * 9. check "do you want to limit the vacancies" and edit 1. + * 10. Save + * 11. Log out TUTOR1 + * 12. log in as TUTOR2 + * 13. go to learning resources, search form + * 14. search for TOPIC_ASSIGNMENT_COURSE and open course run + * 15. go to bb TOPIC_ASSIGNMENT_1 + * 16. check if the button "create topic" is available + * 17. check if "Topic_Tutor1" is available + * 18. click "create topic" + * 19. title: "Topic_Tutor2", description "Description Topic of Tutor 2" + * 20. check "do you want to limit the vacancies" and edit 2. + * 21. Save + * 22. Log out TUTOR2 + * 23. log in as TUTOR3 + * 24. go to learning resources, search form + * 25. search for TOPIC_ASSIGNMENT_COURSE and open course run + * 26. go to bb TOPIC_ASSIGNMENT_1 + * 27. check if the button "create topic" is available + * 28. check if "Topic_Tutor1" and "Topic_Tutor2" are available + * 29. click "create topic" + * 30. title: "Topic_Tutor3", description "Description Topic of Tutor 3" + * 31. check "do you want to limit the vacancies" and edit 3. + * 32. Save + * 33. go again to TOPIC_ASSIGNMENT_1 + * 34. check if all topics are available "Topic_Tutor1", "Topic_Tutor2", "Topic_Tutor3" + * 35. check if in column "in charge" TUTOR1, 2 and 3, respectively, are listed + * 36. check if in the colum "topic status" the first two topics have value "vacancies", the + * third "no participants to check" + * 37. check if in column "number of filled vacancies" is 0 out of 1, 2 and 3 respectively + * 38. check if "select" link is available for all 3 topics + * 39. Log out + * + * </p> + * + * @author sandra + * + */ +public class CreateTopicInTopicAssignmentTest extends BaseSeleneseTestCase { + + private final String NO_TOPIC_AVAILABLE = "No Topics for this Topic assignment available"; + private final String TOPIC_DESCRIPTION_1 = "Description Topic of Tutor 1"; + private final String TOPIC_DESCRIPTION_2 = "Description Topic of Tutor 2"; + private final String TOPIC_DESCRIPTION_3 = "Description Topic of Tutor 3"; + private final String FILLED_VACANCIES_1 = "0 of 1"; + private final String FILLED_VACANCIES_2 = "0 of 2"; + private final String FILLED_VACANCIES_3 = "0 of 3"; + + @Test(dependsOnGroups={TopicAssignmentSuite.FIRST}, groups={TopicAssignmentSuite.SECOND}) + public void testCreateTopicInTopicAssignment() throws Exception { + System.out.println("********* CreateTopicInTopicAssignmentTest **************"); + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //TUTOR1 + OLATWorkflowHelper tutor1Workflow = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, TopicAssignmentSuite.TUTOR1)); + CourseRun courseRun1 = tutor1Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun projectBrokerRun = courseRun1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(projectBrokerRun.isTextPresent(NO_TOPIC_AVAILABLE)); + projectBrokerRun.createTopic(TopicAssignmentSuite.TOPIC_TITLE_1, TOPIC_DESCRIPTION_1, true, 1); + tutor1Workflow.logout(); + + //TUTOR2 + OLATWorkflowHelper tutor2Workflow = context.getOLATWorkflowHelper(context.getOlatLoginInfo(2, TopicAssignmentSuite.TUTOR2)); + CourseRun courseRun2 = tutor2Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun = courseRun2.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun.isTextPresent(TopicAssignmentSuite.TOPIC_TITLE_1)); + topicAssignmentRun.createTopic(TopicAssignmentSuite.TOPIC_TITLE_2, TOPIC_DESCRIPTION_2, true, 2); + tutor2Workflow.logout(); + + //TUTOR3 + OLATWorkflowHelper tutor3Workflow = context.getOLATWorkflowHelper(context.getOlatLoginInfo(2, TopicAssignmentSuite.TUTOR3)); + CourseRun courseRun3 = tutor3Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun3 = courseRun3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun3.isTextPresent(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun3.isTextPresent(TopicAssignmentSuite.TOPIC_TITLE_2)); + topicAssignmentRun3.createTopic(TopicAssignmentSuite.TOPIC_TITLE_3, TOPIC_DESCRIPTION_3, true, 3); + + topicAssignmentRun3 = courseRun3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun3.hasTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun3.hasTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun3.hasTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertTrue(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + + assertTrue(topicAssignmentRun3.isTextPresent(TopicAssignmentSuite.TUTOR1)); + assertTrue(topicAssignmentRun3.isTextPresent(TopicAssignmentSuite.TUTOR2)); + assertTrue(topicAssignmentRun3.isTextPresent(TopicAssignmentSuite.TUTOR3)); + assertTrue(topicAssignmentRun3.isTextPresent(FILLED_VACANCIES_1)); + assertTrue(topicAssignmentRun3.isTextPresent(FILLED_VACANCIES_2)); + assertTrue(topicAssignmentRun3.isTextPresent(FILLED_VACANCIES_3)); + + } +} diff --git a/src/test/java/org/olat/test/functional/course/topic/SelectTopicsAndAcceptCandidatesTest.java b/src/test/java/org/olat/test/functional/course/topic/SelectTopicsAndAcceptCandidatesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2631706fc46d1663f213d8699dcc6b312779bb8a --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/topic/SelectTopicsAndAcceptCandidatesTest.java @@ -0,0 +1,246 @@ +package org.olat.test.functional.course.topic; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TopicAssignmentRun; +import org.olat.test.util.selenium.olatapi.course.run.TopicEditor; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Tests the new bb topic assignment. Step 3: Students choose topics and tutors accept students. + * <br/> + * <p> + * Test setup: <br/> + * 1. course created and modified in CreateAndConfigureTopicAssignmentTest and CreateTopicInTopicAssignmentTest (TOPIC_ASSIGNMENT_COURSE) is available. <br/> + * 2. TUTOR1, TUTOR2, TUTOR3 from CreateAndConfigureTopicAssignmentTest are available <br/> + * 3. prepare following users: STUDENT1, STUDENT2, STUDENT3 <br/> + * + * Testcase:<br/> + * 1. login as STUDENT1 <br/> + * 2. go to learning resources, search form <br/> + * 3. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 4. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 5. check if the button "create topic" is NOT available <br/> + * 6. check if in column "topic status" all three topics have vacancies <br/> + * 7. check if all three select links are available <br/> + * 8. select "Topic_Tutor1" <br/> + * 9. check if in column "topic status" value is "Temporary registration". <br/> + * 10. check if "deselect" link is available <br/> + * 11. select "Topic_Tutor2", do same two checks as above <br/> + * 12. check that student cannot select third topic any more (no select link available). <br/> + * 13. click on title "Topic_Tutor1" <br/> + * 14. click on tab "Folder" <br/> + * 15. check if drop box and return box paragraphes are not available (as only temporarily registered) <br/> + * 16. log out STUDENT1 <br/> + * 17. login as STUDENT2 <br/> + * 18. go to learning resources, search form <br/> + * 19. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 20. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 21. check if in column "topic status" that first topic is filled, other two have vacancies <br/> + * 22. check if two out of three select links are available <br/> + * 23. select "Topic_Tutor2" <br/> + * 24. check if in column "topic status" value is "temporary registration". <br/> + * 25. check if "deselect" link is available <br/> + * 26. select "Topic_Tutor3", do same two checks as above <br/> + * 27. log out STUDENT2 <br/> + * 28. login as STUDENT3 <br/> + * 29. go to learning resources, search form <br/> + * 30. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 31. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 32. check if in column "topic status" that first two topics are filled, only third has vacancies <br/> + * 33. check if one out of three select links are available <br/> + * 34. select "Topic_Tutor3" <br/> + * 35. check if in column "topic status" value is "temporary registration". <br/> + * 36. check if "deselect" link is available <br/> + * 37. log out STUDENT 3 <br/> + * * ----- now tutor view again ------ <br/> + * 38. log in TUTOR1 <br/> + * 39. go to learning resources, search form <br/> + * 40. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 41. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 42. check if following two toolboxes are present "* tutored groups" with link "Topic Topic_Tutor1" and "My learning groups" with link "Administrator Topic assignment" <br/> + * 43. check if in column "topic status" first line is "check participants". second: "filled", third: "vacancies" <br/> + * 44. click on Topic Name "Topic_Tutor2": check if tab "Administration of participants" is not available, back <br/> + * 45. click on Topic Name "Topic_Tutor1" <br/> + * 46. go to tab "Administration of participants" <br/> + * 47. check if in paragraph "Candidates" STUDENT1 is listed <br/> + * 48. check user checkbox, click on "Transfer as participant", no e-mail notification, next <br/> + * 49. check if in paragraph "participants accepted" user STUDENT1 is listed. <br/> + * 50. check if in paragraph "Candidates" STUDENT1 isn't listed anymore <br/> + * 51. click on TOPIC_ASSIGNMENT_1 <br/> + * 52. check if in column "topic status" value is "participants accepted" <br/> + * 53. as STUDENT1 is automatically unsubscribed from "Topic_Tutor2", the second row should have listed "vacancies" "1 of 2" and link "select" is available again. <br/> + * 54. log out TUTOR1 <br/> + * 55. log in TUTOR 3 <br/> + * 56. go to learning resources, search form <br/> + * 57. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 58. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 59. check if in column "topic status" first line is "filled". second: "vacancies", third: "check participants" <br/> + * 60. click on Topic Name "Topic_Tutor3" <br/> + * 61. go to tab "Administration of participants" <br/> + * 62. check if in paragraph "candidates" both STUDENT2 and STUDENT3 are listed. <br/> + * 63. check user "STUDENT3" and click "transfer as participant", no e-mail notification, next <br/> + * 64. click on TOPIC_ASSIGNMENT_1 <br/> + * 65. check if in column "topic status" value is still "check participants" as there are more candidates <br/> + * 66. log out TUTOR3 <br/> + * 67. log in TUTOR2 <br/> + * 68. go to learning resources, search form <br/> + * 69. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 70. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 71. check if in column "topic status" first line is "filled" second: "check participants", third: "vacancies" <br/> + * 72. click on Topic Name "Topic_Tutor2" <br/> + * 73. go to tab "Administration of participants" <br/> + * 74. check STUDENT2 checkbox, click "transfer as participant", no e-mail notification, next <br/> + * 75. log out TUTOR2 <br/> + * + * </p> + * + * @author sandra + * + */ +public class SelectTopicsAndAcceptCandidatesTest extends BaseSeleneseTestCase { + + private final String FILLED_VACANCIES_1_of_2 = "1 of 2"; + + @Override + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //create test users + OlatLoginInfos student1= context.createuserIfNotExists(2, TopicAssignmentSuite.STUDENT1, true, false, false, false, false); + OlatLoginInfos student2= context.createuserIfNotExists(1, TopicAssignmentSuite.STUDENT2, true, false, false, false, false); + OlatLoginInfos student3= context.createuserIfNotExists(2, TopicAssignmentSuite.STUDENT3, true, false, false, false, false); + } + + @Test(dependsOnGroups={TopicAssignmentSuite.SECOND}, groups={TopicAssignmentSuite.THIRD}) + public void testSelectTopicsAndAcceptCandidates() throws Exception { + System.out.println("********* SelectTopicsAndAcceptCandidatesTest **************"); + //STUDENT1 + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.STUDENT1)); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun = courseRun1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + + assertFalse(topicAssignmentRun.canCreateTopic()); + assertTrue(topicAssignmentRun.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertTrue(topicAssignmentRun.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + + topicAssignmentRun.selectTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertTrue(topicAssignmentRun.isTemporaryRegisterd(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_1)); + + topicAssignmentRun.selectTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + assertTrue(topicAssignmentRun.isTemporaryRegisterd(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_2)); + + assertFalse(topicAssignmentRun.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + + TopicEditor topicEditor = topicAssignmentRun.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertFalse(topicEditor.hasDropbox()); + assertFalse(topicEditor.hasReturnbox()); + workflow1.logout(); + workflow1 = null; + + //STUDENT2 + OLATWorkflowHelper workflow2 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(2, TopicAssignmentSuite.STUDENT2)); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun2 = courseRun2.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + + assertTrue(topicAssignmentRun2.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun2.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun2.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + + assertFalse(topicAssignmentRun2.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun2.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun2.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + + topicAssignmentRun2.selectTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + assertTrue(topicAssignmentRun2.isTemporaryRegisterd(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun2.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_2)); + + topicAssignmentRun2.selectTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topicAssignmentRun2.isTemporaryRegisterd(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertTrue(topicAssignmentRun2.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_3)); + workflow2.logout(); + workflow2 = null; + + //STUDENT3 + OLATWorkflowHelper workflow3 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.STUDENT3)); + CourseRun courseRun3 = workflow3.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun3 = courseRun3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun3.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertTrue(topicAssignmentRun3.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun3.isFilled(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertFalse(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertFalse(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + topicAssignmentRun3.selectTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topicAssignmentRun3.isTemporaryRegisterd(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertTrue(topicAssignmentRun3.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_3)); + workflow3.logout(); + workflow3 = null; + + //TUTOR1 + OLATWorkflowHelper tutor1Workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.TUTOR1)); + CourseRun courseRun1Tutor = tutor1Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRunTutor1 = courseRun1Tutor.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + topicAssignmentRunTutor1.hasTutoredGroup(TopicAssignmentSuite.TOPIC_TITLE_1);//"Topic Topic_Tutor1" + + //ask sandra: ??? "My learning groups" with link "Administrator Topic assignment" + assertTrue(topicAssignmentRunTutor1.getCourseRun().hasMyGroup(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1)); + assertTrue(topicAssignmentRunTutor1.hasCheckParticipants(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRunTutor1.isFilled(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRunTutor1.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + TopicEditor topicEditor1 = topicAssignmentRunTutor1.openTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + assertFalse(topicEditor1.hasAdminTab()); + topicAssignmentRunTutor1 = topicEditor1.back(); + + topicEditor1 = topicAssignmentRunTutor1.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertTrue(topicEditor1.hasCandidate(TopicAssignmentSuite.STUDENT1)); + topicEditor1.moveAsParticipant(TopicAssignmentSuite.STUDENT1); + assertTrue(topicEditor1.hasParticipant(TopicAssignmentSuite.STUDENT1)); + assertFalse(topicEditor1.hasCandidate(TopicAssignmentSuite.STUDENT1)); + + topicAssignmentRunTutor1 = courseRun1Tutor.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRunTutor1.hasParticipantsAccepted(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRunTutor1.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRunTutor1.isTextPresent(FILLED_VACANCIES_1_of_2)); + assertTrue(topicAssignmentRunTutor1.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + tutor1Workflow.logout(); + + //TUTOR3 + OLATWorkflowHelper tutor3Workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(2, TopicAssignmentSuite.TUTOR3)); + CourseRun courseRun3Tutor = tutor3Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRunTutor3 = courseRun3Tutor.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRunTutor3.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRunTutor3.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRunTutor3.hasCheckParticipants(TopicAssignmentSuite.TOPIC_TITLE_3)); + TopicEditor topicEditor3 = topicAssignmentRunTutor3.openTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topicEditor3.hasCandidate(TopicAssignmentSuite.STUDENT2)); + assertTrue(topicEditor3.hasCandidate(TopicAssignmentSuite.STUDENT3)); + topicEditor3.moveAsParticipant(TopicAssignmentSuite.STUDENT3); + + topicAssignmentRunTutor3 = courseRun3Tutor.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRunTutor3.hasCheckParticipants(TopicAssignmentSuite.TOPIC_TITLE_3)); + tutor3Workflow.logout(); + + //TUTOR2 + OLATWorkflowHelper tutor2Workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.TUTOR2)); + CourseRun courseRun2Tutor = tutor2Workflow.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRunTutor2 = courseRun2Tutor.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRunTutor2.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRunTutor2.hasCheckParticipants(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRunTutor2.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + TopicEditor topicEditor2 = topicAssignmentRunTutor2.openTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + topicEditor2.moveAsParticipant(TopicAssignmentSuite.STUDENT2); + tutor2Workflow.logout(); + } +} diff --git a/src/test/java/org/olat/test/functional/course/topic/TopicAssignmentSuite.java b/src/test/java/org/olat/test/functional/course/topic/TopicAssignmentSuite.java new file mode 100644 index 0000000000000000000000000000000000000000..573ddfdefa0696eaa7f4bd26b0e1d6ec1c683170 --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/topic/TopicAssignmentSuite.java @@ -0,0 +1,63 @@ +package org.olat.test.functional.course.topic; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + + +/** + * + * @author lavinia + * + */ +public class TopicAssignmentSuite extends TestSuite { + + protected final static String COURSE_NAME = "TOPIC_ASSIGNMENT_COURSE"; //+System.currentTimeMillis(); + protected final static String TUTOR1 = "selenium_tutor1"; + protected final static String TUTOR2 = "selenium_tutor2"; + protected final static String TUTOR3 = "selenium_tutor3"; + protected final static String TOPIC_ASSIGNMENT_1 = "TOPIC_ASSIGNMENT_1"; + protected final static String TOPIC_TITLE_1 = "Topic_Tutor1"; + protected final static String TOPIC_TITLE_2 = "Topic_Tutor2"; + protected final static String TOPIC_TITLE_3 = "Topic_Tutor3"; + + protected final static String STUDENT1 = "selenium_topic_student1"; + protected final static String STUDENT2 = "selenium_topic_student2"; + protected final static String STUDENT3 = "selenium_topic_student3"; + + protected final static String HAND_IN_TOPIC1 = "handInTopic1.pdf"; + protected final static String HAND_IN_TOPIC2 = "handInTopic2.pdf"; + protected final static String HAND_IN_TOPIC3 = "handInTopic3.pdf"; + protected final static String HAND_IN_TOPIC4 = "handInTopic4.pdf"; + + protected final static String HAND_BACK_TOPIC1 = "handBackTopic1.pdf"; + protected final static String HAND_BACK_TOPIC3 = "handBackTopic3.pdf"; + + + final static String FIRST = "TopicAssignmentSuite.FIRST"; + final static String SECOND = "TopicAssignmentSuite.SECOND"; + final static String THIRD = "TopicAssignmentSuite.THIRD"; + + + public static Test suite() { + Context context = Context.setupContext("TopicAssignmentSuite", SetupType.TWO_NODE_CLUSTER); + WorkflowHelper.deleteAllCoursesNamed(COURSE_NAME); + Context.tearDown(); + + TestSuite suite = new TestSuite("TopicAssignmentSuite"); + + suite.addTestSuite(CreateAndConfigureTopicAssignmentTest.class); + suite.addTestSuite(CreateTopicInTopicAssignmentTest.class); + suite.addTestSuite(SelectTopicsAndAcceptCandidatesTest.class); + suite.addTestSuite(UploadInTopicsTest.class); + + return suite; + } + + + +} diff --git a/src/test/java/org/olat/test/functional/course/topic/UploadInTopicsTest.java b/src/test/java/org/olat/test/functional/course/topic/UploadInTopicsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..48ca179016288de56c347bfbaa4be3dc20baa1aa --- /dev/null +++ b/src/test/java/org/olat/test/functional/course/topic/UploadInTopicsTest.java @@ -0,0 +1,245 @@ +package org.olat.test.functional.course.topic; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TopicAssignmentRun; +import org.olat.test.util.selenium.olatapi.course.run.TopicEditor; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Tests the new bb topic assignment. Step 4: Students hand in documents, tutors hands back documents + * <br/> + * <p> + * Test setup:<br/> + * 1. course created and modified in CreateAndConfigureTopicAssignmentTest, CreateTopicInTopicAssignmentTest and SelectTopicsAndAcceptCandidates (TOPIC_ASSIGNMENT_COURSE) is available. <br/> + * 2. TUTOR1, TUTOR2, TUTOR3 from CreateAndConfigureTopicAssignmentTest and STUDENT1, STUDENT2, STUDENT3 from SelectTopicsAndAcceptCandidatesTest are available <br/> + * 3. prepare files HAND_IN_TOPIC1,HAND_IN_TOPIC2, HAND_IN_TOPIC3 and HAND_IN_TOPIC4 (e.g. pdf file) for upload in drop box <br/> + * 4. prepare files HAND_BACK_TOPIC1,HAND_BACK_TOPIC3 (e.g. pdf file) for upload in return box <br/> + * + * Testcase:<br/> + * 1. log in as STUDENT1 <br/> + * 2. go to learning resources, search form <br/> + * 3. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 4. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 5. check if toolbox "my learning groups" shows "Topic Topic_Tutor1" <br/> + * 6. check if column "topic status" shows "positive registration", "vacancies", "vacancies" <br/> + * 7. check if neither select nor deselect links are available any more <br/> + * 8. click on "Topic_Tutor1", go to tab "Folder" <br/> + * 9. check if Drop box and Return box paragraphs are there. <br/> + * 10. check if in paragraph Drop box String "you have not uploaded any files yet" is present <br/> + * 10. upload file HAND_IN_TOPIC1 (sorry there are two no 10.) <br/> + * 11. log out STUDENT1 <br/> + * 12. log in as STUDENT2 <br/> + * 13. go to learning resources, search form <br/> + * 14. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 15. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 16. check if toolbox "my learning groups" shows "Topic Topic_Tutor2" <br/> + * 17. check if column "topic status" shows "filled", "positive registration", "vacancies" <br/> + * 18. check if neither select nor deselect links are available any more <br/> + * 19. click on "Topic_Tutor1", go to tab "Folder" <br/> + * 20. check if Drop box and Return box paragraphs are not available because STUDENT2 is registered for Topic_Tutor2 <br/> + * 21. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 22. click on "Topic_Tutor2", go to tab "Folder" <br/> + * 23 check if Drop box and Return box paragraphs are there <br/> + * 24. upload file HAND_IN_TOPIC2 <br/> + * 25. log out STUDENT2 <br/> + * 26. log in as STUDENT3 <br/> + * 27. go to learning resources, search form <br/> + * 28. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 29. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 30. check if toolbox "my learning groups" shows "Topic Topic_Tutor3" <br/> + * 31. check if column "topic status" shows "vacancies", "vacancies", "positive registration" <br/> + * 32. check if neither select nor deselect links are available any more <br/> + * 33. click on "Topic_Tutor3", go to tab "Folder" <br/> + * 34. check if Drop box and Return box paragraphs are there. <br/> + * 35. upload files HAND_IN_TOPIC3 and HAND_IN_TOPIC4 <br/> + * 36. log out STUDENT3 <br/> + * -- tutor view now--- <br/> + * 37. log in as TUTOR1 <br/> + * 38. go to learning resources, search form <br/> + * 28. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 29. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 30. click on "Topic_Tutor2", go to tab "Folder" <br/> + * 31. check if drop box and return box are not available because TUTOR1 doesn't tutor this topic <br/> + * 32. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 33. click on "Topic_Tutor1", go to tab "Folder" <br/> + * 34. check if in both drop box and return box folder "STUDENT1" appears <br/> + * 35. open drop box folder "STUDENT1" and check if HAND_IN_TOPIC1 is there <br/> + * 36. open return box folder "STUDENT1" and upload HAND_BACK_TOPIC1 <br/> + * 37. log out TUTOR1 <br/> + * 38. log in as TUTOR3 <br/> + * 39. go to learning resources, search form <br/> + * 40. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 41. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 42. click on "Topic_Tutor3", go to tab "Folder" <br/> + * 43. check if in both drop box and return box folder "STUDENT3" appears <br/> + * 44. open drop box folder "STUDENT3" and check if HAND_IN_TOPIC3 and HAND_IN_TOPIC4 are there <br/> + * 45. open return box folder "STUDENT3" and upload HAND_BACK_TOPIC3 <br/> + * 46. log out TUTOR3 <br/> + * --- student view now--- <br/> + * 47. log in as STUDENT1 <br/> + * 48. go to learning resources, search form <br/> + * 49. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 50. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 51. click on "Topic_Tutor1", go to tab "Folder" <br/> + * 52. check if in return box HAND_BACK_TOPIC1 is there <br/> + * 53. log out STUDENT1 <br/> + * 54. log in as STUDENT3 <br/> + * 55. go to learning resources, search form <br/> + * 56. search for TOPIC_ASSIGNMENT_COURSE and open course run <br/> + * 57. go to bb TOPIC_ASSIGNMENT_1 <br/> + * 58. click on "Topic_Tutor3", go to tab "Folder" <br/> + * 59. check if in return box HAND_BACK_TOPIC3 is there <br/> + * 60. log out STUDENT3 <br/> + * + * </p> + * + * @author sandra + * + */ +public class UploadInTopicsTest extends BaseSeleneseTestCase { + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + } + + @Test(dependsOnGroups={TopicAssignmentSuite.THIRD}) + public void testCreateAndConfigureTopicAssignment() throws Exception { + System.out.println("********* UploadInTopicsTest **************"); + + //STUDENT1 + OLATWorkflowHelper workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.STUDENT1)); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun = courseRun1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun.getCourseRun().hasMyGroup(TopicAssignmentSuite.TOPIC_TITLE_1)); //"my learning groups" shows "Topic Topic_Tutor1" + + assertTrue(topicAssignmentRun.isRegistered(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertFalse(topicAssignmentRun.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertFalse(topicAssignmentRun.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_1)); + + TopicEditor topicEditor = topicAssignmentRun.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertTrue(topicEditor.hasDropbox()); + assertTrue(topicEditor.hasReturnbox()); + assertTrue(topicEditor.isTextPresent("You have not uploaded any files yet")); + + File pdf1 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_IN_TOPIC1); + String remotePdf1 = Context.getContext().provideFileRemotely(pdf1); + topicEditor.uploadFileInDropBox(remotePdf1); + workflow1.logout(); + + //STUDENT2 + OLATWorkflowHelper workflow2 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(2, TopicAssignmentSuite.STUDENT2)); + CourseRun courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun1 = courseRun2.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun1.getCourseRun().hasMyGroup(TopicAssignmentSuite.TOPIC_TITLE_2)); + + assertTrue(topicAssignmentRun1.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun1.isRegistered(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun1.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_3)); + + assertFalse(topicAssignmentRun1.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertFalse(topicAssignmentRun1.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_2)); + + TopicEditor topicEditor21 = topicAssignmentRun1.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertFalse(topicEditor21.hasDropbox()); + assertFalse(topicEditor21.hasReturnbox()); + + TopicAssignmentRun topicAssignmentRun2 = courseRun2.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + TopicEditor topicEditor22 = topicAssignmentRun2.openTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + + assertTrue(topicEditor22.hasDropbox()); + assertTrue(topicEditor22.hasReturnbox()); + + File pdf2 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_IN_TOPIC2); + String remotePdf2 = Context.getContext().provideFileRemotely(pdf2); + topicEditor22.uploadFileInDropBox(remotePdf2); + workflow2.logout(); + + //STUDENT3 + OLATWorkflowHelper workflow3 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.STUDENT3)); + CourseRun courseRun3 = workflow3.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentRun3 = courseRun3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + assertTrue(topicAssignmentRun3.getCourseRun().hasMyGroup(TopicAssignmentSuite.TOPIC_TITLE_3)); //"my learning groups" shows "Topic Topic_Tutor3" + + assertTrue(topicAssignmentRun3.isFilled(TopicAssignmentSuite.TOPIC_TITLE_1)); + assertTrue(topicAssignmentRun3.hasVacancies(TopicAssignmentSuite.TOPIC_TITLE_2)); + assertTrue(topicAssignmentRun3.isRegistered(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertFalse(topicAssignmentRun3.canSelectTopic(TopicAssignmentSuite.TOPIC_TITLE_3)); + assertFalse(topicAssignmentRun3.canDeselect(TopicAssignmentSuite.TOPIC_TITLE_3)); + + TopicEditor topicEditor3 = topicAssignmentRun3.openTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topicEditor3.hasDropbox()); + assertTrue(topicEditor3.hasReturnbox()); + + File pdf3 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_IN_TOPIC3); + String remotePdf3 = Context.getContext().provideFileRemotely(pdf3); + topicEditor3.uploadFileInDropBox(remotePdf3); + File pdf4 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_IN_TOPIC4); + String remotePdf4 = Context.getContext().provideFileRemotely(pdf4); + topicEditor3.uploadFileInDropBox(remotePdf4); + workflow3.logout(); + + //tutor view now + //TUTOR1 + OLATWorkflowHelper workflowTutor1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(2, TopicAssignmentSuite.TUTOR1)); + CourseRun courseRunTutor1 = workflowTutor1.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentTutor11 = courseRunTutor1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + + TopicEditor topicEditorTutor12 = topicAssignmentTutor11.openTopic(TopicAssignmentSuite.TOPIC_TITLE_2); + assertFalse(topicEditorTutor12.hasDropbox()); + assertFalse(topicEditorTutor12.hasReturnbox()); + + topicAssignmentTutor11 = courseRunTutor1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + TopicEditor topicEditorTutor11 = topicAssignmentTutor11.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertTrue(topicEditorTutor11.hasDropbox()); + assertTrue(topicEditorTutor11.hasReturnboxFolder(TopicAssignmentSuite.STUDENT1)); + assertTrue(topicEditorTutor11.hasFileInDropBoxFolder(TopicAssignmentSuite.STUDENT1, TopicAssignmentSuite.HAND_IN_TOPIC1)); + + File file1 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_BACK_TOPIC1); + String remoteFilePath1 = Context.getContext().provideFileRemotely(file1); + topicEditorTutor11.uploadFileInReturnBoxFolder(TopicAssignmentSuite.STUDENT1, remoteFilePath1); + workflowTutor1.logout(); + + //TUTOR3 + OLATWorkflowHelper workflowTutor3 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.TUTOR3)); + CourseRun courseRunTutor3 = workflowTutor3.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + TopicAssignmentRun topicAssignmentTutor31 = courseRunTutor3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + TopicEditor topiceEditorTutor33 = topicAssignmentTutor31.openTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topiceEditorTutor33.hasReturnbox()); + assertTrue(topiceEditorTutor33.hasDropbox()); + assertTrue(topiceEditorTutor33.hasFileInDropBoxFolder(TopicAssignmentSuite.STUDENT3, TopicAssignmentSuite.HAND_IN_TOPIC3)); + assertTrue(topiceEditorTutor33.hasFileInDropBoxFolder(TopicAssignmentSuite.STUDENT3, TopicAssignmentSuite.HAND_IN_TOPIC4)); + + File file2 = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + TopicAssignmentSuite.HAND_BACK_TOPIC3); + String remoteFilePath2 = Context.getContext().provideFileRemotely(file2); + topiceEditorTutor33.uploadFileInReturnBoxFolder(TopicAssignmentSuite.STUDENT3, remoteFilePath2); + workflowTutor3.logout(); + + //student view now + + //STUDENT1 + workflow1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(2, TopicAssignmentSuite.STUDENT1)); + courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + topicAssignmentRun = courseRun1.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + TopicEditor topicEditor1 = topicAssignmentRun.openTopic(TopicAssignmentSuite.TOPIC_TITLE_1); + assertTrue(topicEditor1.hasFileInReturnBoxFolder(TopicAssignmentSuite.HAND_BACK_TOPIC1)); + workflow1.logout(); + + //STUDENT3 + workflow3 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, TopicAssignmentSuite.STUDENT3)); + courseRun3 = workflow3.getLearningResources().searchAndShowCourseContent(TopicAssignmentSuite.COURSE_NAME); + topicAssignmentRun3 = courseRun3.selectTopicAssignment(TopicAssignmentSuite.TOPIC_ASSIGNMENT_1); + topicEditor3 = topicAssignmentRun3.openTopic(TopicAssignmentSuite.TOPIC_TITLE_3); + assertTrue(topicEditor3.hasFileInReturnBoxFolder(TopicAssignmentSuite.HAND_BACK_TOPIC3)); + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_EditCoursePreviewRunTest.java b/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_EditCoursePreviewRunTest.java new file mode 100644 index 0000000000000000000000000000000000000000..91487ae437b968792db80c8ec2b0d47001227bb9 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_EditCoursePreviewRunTest.java @@ -0,0 +1,72 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.SinglePageEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.InsertPosition; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * + * Tests changes in previews of course and single page + * <br/> + * <p> + * Test setup:<br/> + * 1. Standardauthor greates course COURSE_NAME<br/> + * 2. cleanup in the end: delete learning resource<br/> + * <br/> + * Test case: <br/> + * 1. Test case: <br/> + * login as author <br/> + * create course <br/> + * insert elements <br/> + * insert information at structure and single pages, edit html pages of single pages, publish <br/> + * edit, move nodes, delete nodes, preview, publish <br/> + * delete course <br/> + * </p> + * + * @author alberto + * + */ + + +public class CourseEditor_EditCoursePreviewRunTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + public void testEditCoursePreviewRunTest() throws Exception { + + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + SinglePageEditor singlePageEditor = (SinglePageEditor)courseEditor.insertCourseElement(CourseElemTypes.SINGLE_PAGE, true, null); + singlePageEditor.setDescription("This is the course TS090533 Description"); + singlePageEditor.createHTMLPage("Firstnode_HTML_Descr", "This is the"); + singlePageEditor.preview(); + singlePageEditor.closePreview(); + + CourseElementEditor courseElementEditor = courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, null); + courseElementEditor.setDescription("This is the description of first structure node"); + courseEditor.publishCourse(); + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + courseEditor = lRDetailedView.editCourseContent(); + courseEditor.selectCourseElement(CourseEditor.STRUCTURE_TITLE); + courseEditor.moveCourseElement(InsertPosition.FIRST_CHILD_OF_ROOT, null); + + courseEditor.selectCourseElement(CourseEditor.SINGLE_PAGE_TITLE); + courseEditor.deleteCourseElement(); + courseEditor.selectCourseElement(CourseEditor.STRUCTURE_TITLE); + courseEditor.deleteCourseElement(); + //TODO: LD: selective publishing + courseEditor.publishCourse(); + courseEditor.preview(); + courseEditor.closeToLRDetailedView().deleteLR(); + olatWorkflow.logout(); + + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_concurrencyEditAndExportTest.java b/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_concurrencyEditAndExportTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ec81f8f513983764ca314360898558eeafd3c669 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CourseEditor_concurrencyEditAndExportTest.java @@ -0,0 +1,84 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * admin starts course editor of a course, author tries to export/download the same course at the same time + * <br/> + * <p> + * Test setup:<br/> + * 1. admin user creates course<br/> + * 2. author user is also owner of the course<br/> + * 3. cleanup in the end: admin deletes course<br/> + * + * Test case: <br/> + * 1. admin creates course<br/> + * 2. admin assigns author as owner<br/> + * 3. admin opens courseeditor<br/> + * 4. author views the detail view of the same course<br/> + * 5. author tries to download the same course at the same time as admin is in the courseeditor<br/> + * 6. assert that the correct message is displayed "This course is currently edited by admin and therefore locked."<br/> + * 7. admin exits courseeditor<br/> + * 8. admin deletes course <br/> + * </p> + * + * @author kristina + * + */ + + +public class CourseEditor_concurrencyEditAndExportTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + + + private CourseEditor courseEditor1; + + + public void testCourseEditor_concurrencyEditAndExportTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OlatLoginInfos user1 = context.getStandardAdminOlatLoginInfos(); + OlatLoginInfos user2 = context.getStandardAuthorOlatLoginInfos(); + + { + //user1 creates course COURSE_NAME with the element "forum" and adds user 2 as owner + System.out.println("logging in browser 1..."); + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(user1); + courseEditor1 = olatWorkflow1.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + LRDetailedView lRDetailedView = courseEditor1.closeToLRDetailedView(); + lRDetailedView.assignOwner(user2.getUsername()); + courseEditor1 = lRDetailedView.editCourseContent(); + } + + { + // open detailed view of 'CourseName' with browser 2 + System.out.println("logging in browser 2..."); + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(user2); + LRDetailedView lRDetailedView2 = workflow2.getLearningResources().searchMyResource(COURSE_NAME); + lRDetailedView2.exportLR(); + + // and wait until 'This course is currently edited by user1 and therefore locked.' appears + SeleniumHelper.waitUntilTextPresent(lRDetailedView2.getSelenium(), "This course is currently locked by "+user1.getUsername()+" due to editing purposes.", 20); + } + + { + // now click 'Close editor' in browser 1 + LRDetailedView lRDetailedView1 = courseEditor1.closeToLRDetailedView(); + + // delete course + lRDetailedView1.deleteLR(); + } + } +} + diff --git a/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateClusterTest.java b/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateClusterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f57d256dbeedf89db76c7e7789da94651c169b42 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateClusterTest.java @@ -0,0 +1,120 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.StructureEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.i18n.LocalStringProvider; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests that after course publish, any other user that has the course open gets a + * "This course has been modified" message, and must close the course tab. + * + * @author eglis + * + */ +public class CoursePublishInvalidateClusterTest extends BaseSeleneseTestCase { + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_2; + private final String COURSE_NAME = "CoursePublishInvalidate" + System.currentTimeMillis(); + + private OlatLoginInfos user1; + + + public void testMultiBrowserClusterCourseViewPublish() throws Exception { + + com.thoughtworks.selenium.Selenium selenium1; + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + user1 = context.createuserIfNotExists(1, "mbcnla1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "mbcnla2", standardPassword, true, true, true, true, true); + + //clone DEMO_COURSE_NAME and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + { + // open the course 'Demo course wiki', modify it and get ready to hit the publish button + System.out.println("logging in browser 1..."); + OLATWorkflowHelper workflow1 = context.getOLATWorkflowHelper(user1); + CourseEditor courseEditor = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME).getCourseEditor(); + StructureEditor structureEditor = courseEditor.getRoot(COURSE_NAME); + structureEditor.setTitle("mod"); + //start publishing + selenium1 = courseEditor.getSelenium(); + selenium1.click("ui=courseEditor::toolbox_editorTools_publish()"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium1.isTextPresent("Publishing")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium1.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + selenium1.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + selenium1.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + assertTrue(selenium1.isTextPresent("No problems found")); + selenium1.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + //assertTrue(selenium1.isTextPresent("Do you really want to publish this course?")); + assertTrue(selenium1.isTextPresent(LocalStringProvider.COURSE_PUBLISH_CONFIRM)); + } + + CourseRun courseRun2; + { + // open 'Demo course wiki' with browser 2 + System.out.println("logging in browser 2..."); + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(user2); + courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + } + + { + // now trigger the publish in browser 1 + selenium1.click("ui=courseEditor::publishDialog_finish()"); + for (int second = 0;; second++) { + if (second >= 20) fail("timeout"); + try { if (selenium1.isTextPresent("Selected modifications published successfully")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + } + + { + // after that, any click course run 2 (browser 2) + //the root node gets modified, but the old browser session still shows + // "OLAT: Demo course" as root entry. click on it will trigger the "this course has been modified + if (courseRun2.getSelenium().isTextPresent("OLAT: Demo course")) { + courseRun2.selectRoot("OLAT: Demo course"); + } + // and waits until 'This course has been modified.' appears + SeleniumHelper.waitUntilTextPresent(courseRun2.getSelenium(),"This course has been modified.", 20); + // excellent, close course in browser 2 + courseRun2.close(COURSE_NAME); + } + + } + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + + try { + //make sure you use the same user for cleanup, since the course could be locked + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(user1); + workflow.getLearningResources().searchResource(COURSE_NAME, null).deleteLR(); + workflow.logout(); + } catch (Exception e) { + System.out.println("Exception while tried to delete the test course!!!"); + } + + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateSingleVMTest.java b/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateSingleVMTest.java new file mode 100644 index 0000000000000000000000000000000000000000..416209e0a714dc8719ba1ebeaa8a57573b631bb0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CoursePublishInvalidateSingleVMTest.java @@ -0,0 +1,71 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests that after course publish, any other user that has the course open gets a + * "This course has been modified" message, and must close the course tab. + * + * @author eglis + * + */ +public class CoursePublishInvalidateSingleVMTest extends BaseSeleneseTestCase { + + //TODO: LD: import test course instead of cloning the DEMO_COURSE_NAME + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_2; + private final String COURSE_NAME = "CoursePublishInvalidate" + System.currentTimeMillis(); + + public void testMultiBrowserCourseViewPublish() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + + //clone DEMO_COURSE_NAME and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + OLATWorkflowHelper workflow_1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + OLATWorkflowHelper workflow_2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + + // open the course 'Demo course wiki', modify it and get ready to hit the publish button + System.out.println("logging in browser 1..."); + CourseRun courseRun_1 = workflow_1.getLearningResources().searchAndShowMyCourseContent(COURSE_NAME); + Thread.sleep(9000); + CourseEditor courseEditor_1 = courseRun_1.getCourseEditor(); + CourseElementEditor courseElementEditor = courseEditor_1.selectCourseElement(COURSE_NAME); + courseElementEditor.setTitle("mod"); + + // open 'Demo course wiki' with browser 2 + System.out.println("logging in browser 2..."); + CourseRun courseRun_2 = workflow_2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + + // now trigger the publish in browser 1 + courseEditor_1.publishCourse(); + + // after that, click 'Wiki sandbox' in browser 2 + if(courseRun_2.isTextPresent("Wiki sandbox")) { + courseRun_2.selectCourseElement("Wiki sandbox"); + } + //and wait until 'This course has been deleted.' appears + SeleniumHelper.waitUntilTextPresent(courseRun_2.getSelenium(), "This course has been modified.", 60); //increased timeout + + // excellent, close course in browser 2 + courseRun_2.close(COURSE_NAME); + } + + @Override + protected void cleanUpAfterRun() { + try { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + workflow.getLearningResources().searchMyResource(COURSE_NAME).deleteLR(); + } catch (Exception e) { + System.out.println("Exception while tried to delete test course!!!"); + e.printStackTrace(); + } + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CourseRenameTest.java b/src/test/java/org/olat/test/functional/courseeditor/CourseRenameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..006e14faf3ae3b37f8fd2020e023faa89a2059db --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CourseRenameTest.java @@ -0,0 +1,63 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.StructureElement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests the course title change and publish. + * Test setup & test case: + * Admin creates a clone of "Demo course wiki" course, publishes it, changes the title, + * publishes again, asserts if the course title was changed. Cleanup. + * + * + * @author lavinia + * + */ +public class CourseRenameTest extends BaseSeleneseTestCase { + + private final String DEMO_COURSE_NAME = Context.DEMO_COURSE_NAME_2; + private final String COURSE_NAME = "CourseRename" + System.currentTimeMillis(); + + public void testCoursePublish() throws Exception { + System.out.println("CoursePublishTest - before setupContext"); + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + System.out.println("CoursePublishTest - after setupContext"); + + //clone DEMO_COURSE_NAME and work with the clone + assertTrue(WorkflowHelper.cloneCourse(context, DEMO_COURSE_NAME, COURSE_NAME)); + + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + System.out.println("CoursePublishTest - logged in"); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + Thread.sleep(9000); + CourseEditor courseEditor = courseRun.getCourseEditor(); + CourseElementEditor courseElementEditor = courseEditor.selectCourseElement(COURSE_NAME); + courseElementEditor.setTitle("mod"); + courseEditor.publishCourseAfterCourseTitleChanged(); + courseRun = courseEditor.closeToCourseRun(); + //asserts that root changed the title + StructureElement root = courseRun.selectRoot("mod"); + courseRun.close(COURSE_NAME); + } + + + @Override + public void cleanUpAfterRun() { + try { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + workflow.getLearningResources().searchMyResource(COURSE_NAME).deleteLR(); + } catch (Exception e) { + System.out.println("Exception while tried to delete test course!!!"); + e.printStackTrace(); + } + } + + +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CreateBlogTest.java b/src/test/java/org/olat/test/functional/courseeditor/CreateBlogTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3628bd58835eb0afc942000e37c09319bbdc0b60 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CreateBlogTest.java @@ -0,0 +1,107 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.BlogEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.BlogResource; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests the Blog BB and Blog Editor with both configurations internal and external + * <br/> + * <p> + * Test case: <br/> + * create course and add blog elements for internal and external blog <br/> + * edit internal blog <br/> + * edit blog in new tab <br/> + * close blog tab <br/> + * edit external blog <br/> + * close blog tab <br/> + * go back to course editor <br/> + * publish and check course view <br/> + * check content - assert <br/> + * delete course <br/> + * delete blog resource <br/> + * + * + * @author sandra, alberto + */ +public class CreateBlogTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "BlogCourse"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + private final String EXT_BLOG = "An External Blog"; + private final String INT_BLOG = "My Internal Blog"; + private final String INT_BLOG_MOD = "Mod Internal"; + private final String BLOG_DESC = "My First Blog"; + private final String BLOG_TITEL_OF_CONTENT = "Dubai"; + private final String BLOG_DESC_OF_CONTENT = "My Dubai trip"; + private final String BLOG_CONTENT = "trip to Dubai entry description"; + + + + + public void testCreateBlog() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + // create course and add blog elements for internal and external blog + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.BLOG, true, INT_BLOG); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.BLOG, true, EXT_BLOG); + + // edit internal blog + courseEditor.selectCourseElement(INT_BLOG); + BlogEditor blogEditorInt = (BlogEditor)courseEditor.selectCourseElement(INT_BLOG); + blogEditorInt.create(INT_BLOG, BLOG_DESC); + + // edit blog in new tab + BlogResource blogResource_1 = blogEditorInt.edit(); + blogResource_1.editBlog(INT_BLOG_MOD, "Trips around the world", null); + blogResource_1.createEntry(BLOG_TITEL_OF_CONTENT, BLOG_DESC_OF_CONTENT, BLOG_CONTENT, true); + + //close blog tab + LRDetailedView lRDetailedView = blogResource_1.close(); + courseEditor = lRDetailedView.editCourseContent(); + + // edit external blog + BlogEditor blogEditorExt = (BlogEditor)courseEditor.selectCourseElement(EXT_BLOG); + blogEditorExt.select(INT_BLOG_MOD); + BlogResource blogResource_2 = blogEditorExt.edit(); + + // close blog tab + LRDetailedView lRDetailedView2 = blogResource_2.close(); + // go back to course editor + courseEditor = lRDetailedView2.editCourseContent(); + + // publish and check course view + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + + //check content + courseRun.selectCourseElement(EXT_BLOG); + assertTrue(courseRun.isTextPresent(BLOG_TITEL_OF_CONTENT)); + assertTrue(courseRun.isTextPresent(BLOG_DESC_OF_CONTENT)); + + } + + + @Override + protected void cleanUpAfterRun() { + OLATWorkflowHelper olatWorkflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos()); + //delete course + LRDetailedView lRDetailedView3 = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME); + LearningResources lrs = lRDetailedView3.deleteLR(); + //delete blog ressource + LRDetailedView lRDetailedView4 = lrs.searchMyResource(INT_BLOG_MOD); + lRDetailedView4.deleteLR(); + } + + +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/CreatePodcastTest.java b/src/test/java/org/olat/test/functional/courseeditor/CreatePodcastTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dd3453d46395ef4ded4eb0ebbbf1121957246299 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/CreatePodcastTest.java @@ -0,0 +1,118 @@ +package org.olat.test.functional.courseeditor; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CoursePreview; +import org.olat.test.util.selenium.olatapi.course.editor.PodcastEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.PodcastResource; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the Podcast BB and Podcast Editor with both configurations internal and external + * <br/> + * <p> + * Test case: <br/> + * create course with podcast element <br/> + * create 1 podcast whose entries are created within olat <br/> + * create 1 external podcast <br/> + * publish <br/> + * preview course <br/> + * check content of external podcast <br/> + * check content of internal podcast <br/> + * check content as student <br/> + * delete course and delete podcast resources <br/> + * + * + * @author alberto + */ +public class CreatePodcastTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CreatePodcast"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + private final String INT_PODCAST = "Internal"; + private final String EXT_PODCAST = "External"; + private final String EXT_PODCAST_DESC = "First external Podcast"; + private final String INT_PODCAST_DESC = "First OLAT Podcast"; + + + public void testCreatePodcast() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + // create course and add podcast elements for internal and external podcast + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.PODCAST, true, INT_PODCAST); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.PODCAST, true, EXT_PODCAST); + + //create 1 podcast whose entries are created within olat + courseEditor.selectCourseElement(INT_PODCAST); + PodcastEditor podcastEditorInt = (PodcastEditor)courseEditor.selectCourseElement(INT_PODCAST); + podcastEditorInt.create(INT_PODCAST, INT_PODCAST_DESC); + + //create 1 external podcast + courseEditor.selectCourseElement(EXT_PODCAST); + PodcastEditor podcastEditorExt = (PodcastEditor)courseEditor.selectCourseElement(EXT_PODCAST); + podcastEditorExt.create(EXT_PODCAST, EXT_PODCAST_DESC); + PodcastResource podcastResource = podcastEditorExt.edit(); + podcastResource.includeExternal(EXT_PODCAST, EXT_PODCAST_DESC, "feed://pod.drs.ch/focus_-_die_talkshow_mpx.xml"); + LRDetailedView lrDetailedView = podcastResource.close(); + + //create Episode + courseEditor = lrDetailedView.editCourseContent(); + podcastEditorInt = (PodcastEditor)courseEditor.selectCourseElement(INT_PODCAST); + podcastResource = podcastEditorInt.edit(); + File mediaFile = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "firstmedia.flv"); + String remoteFile = Context.getContext().provideFileRemotely(mediaFile); + podcastResource.createEpisode("Episode_title", "Episode_description", remoteFile); + LRDetailedView lRDetailedView = podcastResource.close(); + + // publish + courseEditor = lrDetailedView.editCourseContent(); + courseEditor.publishCourse(); + + //preview course + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + courseRun.selectCourseElement(EXT_PODCAST); + + //check content of external podcast + assertTrue(courseRun.isTextPresent(EXT_PODCAST_DESC)); + + //check content of internal podcast + courseRun.selectCourseElement(INT_PODCAST); + assertTrue(courseRun.isTextPresent(INT_PODCAST_DESC)); + + //preview as student + courseEditor = courseRun.getCourseEditor(); + CoursePreview coursePreview = courseEditor.openPreview(); + coursePreview.showPreview(); + + //check content as student + assertTrue(courseRun.isTextPresent("Course element of the type Podcast")); + coursePreview.selectCourseElement(EXT_PODCAST); + //TODO: When Podcast element has a preview, replace next line with accordingly + assertTrue(courseRun.isTextPresent("No preview available for this course element")); + coursePreview.selectCourseElement(EXT_PODCAST); + + //delete course and delete resource + courseEditor = coursePreview.closePreview(); + courseRun = courseEditor.closeToCourseRun(); + lrDetailedView = courseRun.getDetailedView(); + courseRun.close(COURSE_NAME); + LearningResources lrs = lrDetailedView.deleteLR(); + lrDetailedView = lrs.searchMyResource(EXT_PODCAST); + lrs = lrDetailedView.deleteLR(); + lrDetailedView = lrs.searchMyResource(INT_PODCAST); + lrs = lrDetailedView.deleteLR(); + + + } +} \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/courseeditor/DeletePublishIncompleteElementsTest.java b/src/test/java/org/olat/test/functional/courseeditor/DeletePublishIncompleteElementsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a47a95dd6a98d404b82eca234fdf01c3259741f0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/DeletePublishIncompleteElementsTest.java @@ -0,0 +1,97 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CoursePreview; +import org.olat.test.util.selenium.olatapi.course.editor.SinglePageEditor; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.InsertPosition; +import org.olat.test.util.selenium.olatapi.course.editor.CoursePreview.Role; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * Tests incomplete publish workflows + * <br/> + * <p> + * Test case: <br/> + * create course <br/> + * create and insert single page, preview within single page <br/> + * insert structure element <br/> + * leave editor, enter editor <br/> + * copy single page, delete copy <br/> + * preview <br/> + * publish <br/> + * insert single page, create html page and assign to single page <br/> + * delete html-page in the storage folder <br/> + * publish, delete single page, publish <br/> + * delete course and logout <br/> + * + * @author alberto + */ +public class DeletePublishIncompleteElementsTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + + public void testDeletePublishIncompleteElementsTest() throws Exception { + + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + //create course + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + + //create and insert single page, preview within single page + SinglePageEditor singlePageEditor = (SinglePageEditor)courseEditor.insertCourseElement(CourseElemTypes.SINGLE_PAGE, true, "single page1"); + singlePageEditor.setDescription("This is the course TS090533 Description"); + singlePageEditor.createHTMLPage("first_html_descr", "a not very long content that serves as an example"); + singlePageEditor.preview(); + singlePageEditor.closePreview(); + + //insert structure element + CourseElementEditor courseElementEditor = courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "structure1"); + courseElementEditor.setDescription("This is the description of first structure node"); + + //leave editor, enter editor + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + courseEditor = lRDetailedView.editCourseContent(); + + //copy single page, delete copy + courseEditor.selectCourseElement("single page1"); + courseEditor.copyCourseElement(InsertPosition.FIRST_CHILD_OF_ROOT, "single page2"); + courseEditor.deleteCourseElement(); + + //preview + CoursePreview coursePreview = courseEditor.openPreview(); + coursePreview.changeRole(Role.AUTHOR); + coursePreview.showPreview(); + courseEditor = coursePreview.closePreview(); + + //publish + courseEditor.publishCourse(); + + //insert single page, create html page and assign to single page + singlePageEditor = (SinglePageEditor)courseEditor.insertCourseElement(CourseElemTypes.SINGLE_PAGE, true, "single page2"); + singlePageEditor.setDescription("This is the second course TS090533 Description"); + singlePageEditor.createHTMLPage("second_html_descr", "a not very long content that serves as an example too"); + + //delete html-page in the storage folder + Folder storageFolder = courseEditor.storageFolder(); + storageFolder.deleteItem("second_html_descr.html"); + + //publish, delete single page, publish + courseEditor.publishCourse(); + courseEditor.selectCourseElement("single page2"); + courseEditor.deleteCourseElement(); + courseEditor.publishCourse(); + + //delete course and logout + courseEditor.closeToLRDetailedView().deleteLR(); + olatWorkflow.logout(); + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/EnrolmentCreateGroupsWithCSVTest.java b/src/test/java/org/olat/test/functional/courseeditor/EnrolmentCreateGroupsWithCSVTest.java new file mode 100644 index 0000000000000000000000000000000000000000..24bb8fb67ea9ebb2aed1d63e74c83d9c9b8d79c4 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/EnrolmentCreateGroupsWithCSVTest.java @@ -0,0 +1,77 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests Jira Issue OLAT-4515 + * <br/> + * <p> + * Test setup: <br/> + * create course and open course editor <br/> + * insert enrolment element <br/> + * select configuration tab for creating new groups <br/> + * create group gr1 and group gr2 with CSV input <br/> + * assure that group gets added to the group enumeration in the learning group text element <br/> + * Delete groups <br/> + * create groups again, but one more. example: + gr1comma, gr2comma, gr3comma <br/> + * close course <br/> + * </p> + * + * @author alberto + */ +public class EnrolmentCreateGroupsWithCSVTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "EnrollWithCSV"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + private final String GR1 = "gr1comma"; + private final String GR2 = "gr2comma"; + private final String GR3 = "gr3comma"; + + public void testEnrolmentCreateGroupsWithCSV() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + //create course and open course editor + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + + //insert enrolment element + EnrolmentEditor enrolmentEditor = (EnrolmentEditor)courseEditor.insertCourseElement(CourseElemTypes.ENROLMENT, true, null); + + //select configuration tab for creating new groups + //create group gr1 and group gr2 with CSV input + String groupEnumerationString = GR1+","+GR2; + enrolmentEditor.createAndSelectGroups(groupEnumerationString); + assertTrue(enrolmentEditor.isGroupSelected(GR1)); + assertTrue(enrolmentEditor.isGroupSelected(GR2)); + + //delete groups + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + GroupManagement groupManagement = courseRun.getGroupManagement(); + groupManagement.deleteGroup(GR1); + groupManagement.deleteGroup(GR2); + courseRun = groupManagement.close(); + + //create groups again, but one more. in example: gr1comma, gr2comma, gr3comma + courseEditor = courseRun.getCourseEditor(); + enrolmentEditor = (EnrolmentEditor)courseEditor.selectCourseElement(CourseEditor.ENROLMENT_TITLE); + groupEnumerationString += ","+GR3; + enrolmentEditor.createAndSelectGroups(groupEnumerationString); + assertTrue(enrolmentEditor.isGroupSelected(GR1)); + assertTrue(enrolmentEditor.isGroupSelected(GR2)); + assertTrue(enrolmentEditor.isGroupSelected(GR3)); + + //close course + courseEditor.closeToCourseRun().closeAny(); + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/MoveDeleteElementsTest.java b/src/test/java/org/olat/test/functional/courseeditor/MoveDeleteElementsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9d8248abcfcc032e02affb8cbb4f8c6423c614d7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/MoveDeleteElementsTest.java @@ -0,0 +1,131 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CoursePreview; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.InsertPosition; +import org.olat.test.util.selenium.olatapi.course.editor.CoursePreview.Role; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * + * Tests changes in course tree structure by moving and deleting nodes + * <br/> + * <p> + * Test case: <br/> + * login as author <br/> + * create course <br/> + * insert elements with subelements, publish <br/> + * insert more elements with subelements, publish <br/> + * navigate in coursemenu, delete only a subelement, publish <br/> + * delete element with subelements, move first element to last position, publish <br/> + * leave editor, enter editor <br/> + * delete first and last elements, restore first, delete first <br/> + * preview, another preview with modified roles, publish <br/> + * delete course <br/> + * + * @author alberto + */ + +public class MoveDeleteElementsTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseMoveDelete"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + private OLATWorkflowHelper workflow; + + public void testCourseEditor_moveDeleteElementsTest() throws Exception { + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + workflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, true, null); + courseEditor.insertCourseElement(CourseElemTypes.FORUM, false, null); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, false, "Folder1"); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, false, "Folder2"); + courseEditor.publishCourse(); + //close course, start run, start editor + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + courseEditor = lRDetailedView.showCourseContent().getCourseEditor(); + + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, InsertPosition.FOLLOWING_SIBLING_OF_ELEMENT, CourseEditor.STRUCTURE_TITLE, "Structure1"); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, InsertPosition.FIRST_CHILD_OF_ELEMENT, "Structure1", "Folder3"); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, InsertPosition.FIRST_CHILD_OF_ELEMENT, "Structure1", "Folder4"); + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "Structure2"); + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "Structure3"); + + courseEditor.publishFirstChangedElement(); + courseEditor.publishFirstChangedElement(); + + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "Structure4"); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, InsertPosition.FIRST_CHILD_OF_ELEMENT, "Structure4", "Folder5"); + courseEditor.insertCourseElement(CourseElemTypes.FOLDER, InsertPosition.FIRST_CHILD_OF_ELEMENT, "Structure4", "Folder6"); + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "Structure5"); + courseEditor.insertCourseElement(CourseElemTypes.STRUCTURE, false, "Structure6"); + /*while(courseEditor.publishFirstChangedElement()) { + System.out.println("one more node to be published found"); + }*/ + courseEditor.publishCourse(); + + courseEditor.selectCourseElement("Structure4"); + courseEditor.selectCourseElement("Folder6"); + courseEditor.selectCourseElement("Folder5"); + courseEditor.deleteCourseElement(); + courseEditor.publishFirstChangedElement(); + //close course, start run, start editor + CourseRun courseRun = courseEditor.closeToCourseRun(); + assertTrue(courseRun.isTextPresent("Structure6")); + assertFalse(courseRun.isTextPresent("Folder5")); + courseEditor = courseRun.getCourseEditor(); + + courseEditor.selectCourseElement("Structure5"); + courseEditor.selectCourseElement("Structure4"); + courseEditor.deleteCourseElement(); + courseEditor.publishFirstChangedElement(); + courseEditor.selectCourseElement("Structure1"); + courseEditor.moveCourseElement(InsertPosition.LAST_CHILD_OF_ROOT, null); + courseEditor.publishCourse(); + + courseEditor.closeToCourseRun(); + assertFalse(courseRun.isTextPresent("Structure4")); + assertTrue(courseRun.isTextPresent("Structure1")); + + courseEditor = workflow.getLearningResources().searchMyResource(COURSE_NAME).editCourseContent(); + courseEditor.selectCourseElement("Folder2"); + courseEditor.deleteCourseElement(); + courseEditor.selectCourseElement("Structure3"); + courseEditor.deleteCourseElement(); + courseEditor.selectCourseElement("Folder2"); + courseEditor.undeleteCourseElement(); + + + CoursePreview coursePreview = courseEditor.openPreview(); + coursePreview.changeRole(Role.AUTHOR); + coursePreview.changeRole(Role.REGISTERED_USER); + coursePreview.showPreview(); + + //assertFalse(coursePreview.isTextPresent("Structure3")); + assertTrue(coursePreview.isTextPresent("Folder2")); + + //check this out + coursePreview.selectCourseElement("Structure1"); + + courseEditor = coursePreview.closePreview(); + courseEditor.publishCourse(); + courseEditor.closeToCourseRun().close(COURSE_NAME); + + workflow.getLearningResources().searchMyResource(COURSE_NAME).deleteLR(); + } + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + workflow.logout(); + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } + +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/OpenEditSessionTest.java b/src/test/java/org/olat/test/functional/courseeditor/OpenEditSessionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..648ec63751e5cd56acc59ace118b61549340316c --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/OpenEditSessionTest.java @@ -0,0 +1,71 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Test the open/close course edit session. + * See OLAT-4546. + * + * Test case: <br/> + * Author: <br/> + * - creates course, insert node, publish, close course to detail view <br/> + * - open course run from detail view <br/> + * - go to detail view again (select detail view from course run), and modify property (e.g. access) <br/> + * - click edit course (from detail view) and land to the disposed course <br/> + * - click "Close and restart course" -> reopens course run <br/> + * - edit course again (e.g. insert node) and publish. Close course. <br/> + * - delete course. + * + * @author Lavinia Dumitrescu + * + */ +public class OpenEditSessionTest extends BaseSeleneseTestCase { + + private String COURSE_NAME = "AAA"+ System.currentTimeMillis(); + private boolean cleanedUp = false; + + + public void testOpenEditSession() { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla"); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + CourseElementEditor courseElementEditor = courseEditor.selectCourseElement("Forum"); + courseElementEditor.setDescription("NEW DESCRIPTION"); + + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + + LRDetailedView lRDetailedView = courseRun.getDetailedView(); + lRDetailedView.modifyProperties(LRDetailedView.ACCESS_REGISTERED_AND_GUESTS); + + //the course run was disposed due to property change + courseRun = lRDetailedView.selectDisposedCourse().closeCourseAndRestart(); + courseEditor = courseRun.getCourseEditor(); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.STRUCTURE, true, null); + courseEditor.publishCourse(); + //cleanup + courseEditor.closeToCourseRun().getDetailedView().deleteLR(); + cleanedUp = true; + } + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + //cleanup + if(!cleanedUp) { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos()); + workflow.getLearningResources().searchMyResource(COURSE_NAME).deleteLR(); + } + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/courseEditor_concurrenciesEditTest.java b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_concurrenciesEditTest.java new file mode 100644 index 0000000000000000000000000000000000000000..83fb2603273d0bb9cbdcc7ec4d08f24fb7cd1b46 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_concurrenciesEditTest.java @@ -0,0 +1,89 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * + * Assure that owner A and B cannot start editing the same course at the same time. + * <br/> + * <p> + * Test setup:<br/> + * 1. user1 (standardauthor) creates course Coursename<br/> + * 2. user2 (standardstudent) is also owner of course Coursename<br/> + * 3. cleanup in the end: course is deleted<br/> + * + * Test case: <br/> + * 1. user1 creates course "CourseName" with the element "forum" and adds user2 as owner <br/> + * 2. user2 opens detailed view of course "CourseName" in browser 2<br/> + * 3. user1 clicks edit "CourseName" in browser 1<br/> + * 4. user2 clicks "Edit content" in browser 2 <br/> + * 5. Check if the message "This course is currently edited by 'user1' and therefore locked." appears<br/> + * 6. user1 closes editor in browser 1<br/> + * 7. user2 clicks "Edit content" in browser 2<br/> + * 8. Check if "This course has never been published." appears<br/> + * </p> + * + * @author kristina + * + */ +public class courseEditor_concurrenciesEditTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + + public void testcourseEditor_concurrenciesEditTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OlatLoginInfos user1 = context.getStandardAuthorOlatLoginInfos(1); + OlatLoginInfos user2 = context.getStandardStudentOlatLoginInfos(2); + + //user1 creates course COURSE_NAME with the element "forum" and adds user 2 as owner + System.out.println("logging in browser 1..."); + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(user1); + CourseEditor courseEditor = olatWorkflow1.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + lRDetailedView.assignOwner(user2.getUsername()); + + //user 2 opens detailed view of course COURSE_NAME in browser 2 + System.out.println("logging in browser 2..."); + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(user2); + LearningResources learningResources2 = olatWorkflow2.getLearningResources(); + LRDetailedView lRDetailedView2 = learningResources2.searchMyResource(COURSE_NAME); + + //user 1 clicks edit COURSE_NAME in browser 1 + CourseEditor courseEditor3 = lRDetailedView.editCourseContent(); + + //user2 clicks "Edit content" in browser 2 + boolean isCourseLocked = lRDetailedView2.checkCourseLocked(user1.getUsername()); + assertTrue(isCourseLocked); + + //user1 closes editor in browser 1 + courseEditor3.closeToLRDetailedView(); //course run was open via the LRDetailedView + + //user2 clicks "Edit content" in browser 2 + CourseEditor courseEditor4 = lRDetailedView2.editCourseContent(); + + //Check if "This course has never been published." appears + SeleniumHelper.waitUntilTextPresent(lRDetailedView2.getSelenium(), "This course has never been published.", 20); + + //delete course + LRDetailedView lRDetailedView3 = courseEditor4.closeToLRDetailedView(); + try { + lRDetailedView3.deleteLR(); + } catch (Exception e) {} + } +} + + diff --git a/src/test/java/org/olat/test/functional/courseeditor/courseEditor_consistencyPublishTest.java b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_consistencyPublishTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a8eb8f1e43ccec66f301960e04094defdab02798 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_consistencyPublishTest.java @@ -0,0 +1,105 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Cancel publish workflow in different moments of the workflow + * <br/> + * <p> + * Test setup:<br/> + * 1. standardauthor creates course CoursName <br/> + * 2. Cleanup in the end: delete learning resource<br/> + * <br/> + * Test case: <br/> + * 1. create course "CourseName" <br/> + * 2. insert forum, click publish, change access to all registered OLAT users<br/> + * 3. insert structure, click publish, cancel<br/> + * 4. click publish, select all, cancel<br/> + * 5. click publish, click next, cancel<br/> + * 6. click publish, click select all, click next, choose Only owners of this learning resource, cancel<br/> + * 7. click publish, select firstTreeCheckbox, click next, click finish<br/> + * 8. close editor<br/> + * 9. click show content<br/> + * 10. click forum<br/> + * 11. click detail view<br/> + * 12. delete course CourseName <br/> + * </p> + * + * @author kristina + * + */ + +public class courseEditor_consistencyPublishTest extends BaseSeleneseTestCase { + + + public void testcourseEditor_consistencyPublishTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + //selenium = context.createSeleniumAndLogin(context.getStandardAuthorOlatLoginInfos()); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing("CourseName", "CourseDescription"); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + courseEditor.publishCourse(); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.STRUCTURE, true, null); + selenium = courseEditor.getSelenium(); + + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_cancel()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + // cancel publish + selenium.click("ui=courseEditor::publishDialog_cancel()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_selectall()"); + selenium.waitForPageToLoad("30000"); + //cancel publish + selenium.click("ui=courseEditor::publishDialog_cancel()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + //cancel publish + selenium.click("ui=courseEditor::publishDialog_cancel()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_selectall()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.select("ui=courseEditor::publishDialog_courseAccessDropDown()", "label=Only owners of this learning resource"); + //cancel publish + selenium.click("ui=courseEditor::publishDialog_cancel()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_finish()"); + selenium.waitForPageToLoad("30000"); + + //we are still in the courseEditor + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + CourseRun courseRun = lRDetailedView.showCourseContent(); + courseRun.selectCourseElement(CourseEditor.STRUCTURE_TITLE); + courseRun.selectCourseElement(CourseEditor.FORUM_COURSE_ELEM_TITLE); + lRDetailedView = courseRun.getDetailedView(); + try { + lRDetailedView.deleteLR(); + } catch (Exception e) {} + + } +} diff --git a/src/test/java/org/olat/test/functional/courseeditor/courseEditor_insertElementsAMTest.java b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_insertElementsAMTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d8a7abac5a97ae3bf683bbdb75d7e45f066d4ed3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/courseeditor/courseEditor_insertElementsAMTest.java @@ -0,0 +1,105 @@ +package org.olat.test.functional.courseeditor; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.FolderEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.InsertPosition; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * create course with all elements and configure + * <br/> + * <p> + * Test setup:<br/> + * 1. Standardauthor creates course COURSE_NAME<br/> + * 2. cleanup in the end: delete learning resource<br/> + * <br/> + * Test case: <br/> + * 1. create course "CourseName" and start course editor <br/> + * 2. insert structure<br/> + * 3. insert single page<br/> + * 4. insert external page<br/> + * 5. insert cp<br/> + * 6. insert scorm<br/> + * 7. insert forum<br/> + * 8. insert wiki<br/> + * 9. insert file dialog<br/> + * 10. insert folder<br/> + * 11. insert assessment<br/> + * 12. insert task<br/> + * 13. insert test<br/> + * 14. insert selftest<br/> + * 15. insert questionnaire<br/> + * 16. insert enrolment<br/> + * 17. insert contact form<br/> + * 18. move contact form<br/> + * 19. delete contact form<br/> + * 20. click on folder, goto tab visibility<br/> + * 21. choose blocked for learners, save<br/> + * 22. goto tab access, deselect blocked for learner (Read and Write), choose blocked for learners (read only)<br/> + * 23. click course preview<br/> + * 24. close course editor<br/> + * 25. delete course <br/> + * </p> + * + * @author kristina + * + */ + +public class courseEditor_insertElementsAMTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + private final String FOLDER_NAME = "Folder"; + + + public void testcourseEditor_insertElementsAMTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + // create course "CourseName" and start course editor + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + // insert structure, single page, external page etc. + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.STRUCTURE, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.SINGLE_PAGE, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.EXTERNAL_PAGE, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.CP_LEARNING_CONTENT, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.SCORM_LEARNING_CONTENT, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.WIKI, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FILE_DIALOG, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FOLDER, true, FOLDER_NAME); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.ASSESSMENT, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TASK, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TEST, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.SELF_TEST, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.QUESTIONNAIRE, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.ENROLMENT, true, null); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.CONTACT_FORM, true, null); + courseEditor.selectCourseElement(CourseEditor.CONTACT_FORM_TITLE); + courseEditor.moveCourseElement(InsertPosition.FIRST_CHILD_OF_ROOT, null); + courseEditor.selectCourseElement(CourseEditor.CONTACT_FORM_TITLE); + courseEditor.deleteCourseElement(); + + // click on folder, goto tab visibility + FolderEditor folderEditor = (FolderEditor)courseEditor.selectCourseElement(FOLDER_NAME); + // choose blocked for learners, save + folderEditor.changeVisibilityBlockForLearners(); + //goto tab access, deselect blocked for learner (Read and Write), choose blocked for learners (read only) + folderEditor.changeAccessBlockForLearnersReadAndWrite(); + folderEditor.changeAccessBlockForLearnersReadOnly(); + + // click course preview, close preview + courseEditor.preview(); + // close course editor + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + try { + // delete course + lRDetailedView.deleteLR(); + } catch (Exception e) {} + } +} diff --git a/src/test/java/org/olat/test/functional/group/management/CollaborationToolsTest.java b/src/test/java/org/olat/test/functional/group/management/CollaborationToolsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..49294faf6df28dc3d8f23d7e56b3dd2bd537d167 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/CollaborationToolsTest.java @@ -0,0 +1,49 @@ +package org.olat.test.functional.group.management; + +import org.junit.Ignore; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * test groupChat stuff and polling (changing interval) + * + * @author Guido + * + */ +@Ignore +public class CollaborationToolsTest extends BaseSeleneseTestCase { + + + private OLATWorkflowHelper workflow1; + private OLATWorkflowHelper workflow2; + + public void testCourseChat() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + workflow1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + workflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + + String nameOfGroup ="junittest-"+System.currentTimeMillis(); + //browser 1 + GroupAdmin groupAdmin1 = workflow1.getGroups().createProjectGroup(nameOfGroup, "junittest"); + groupAdmin1.setTools(true, true, true, true, true, false, true); + String[] owners = {context.getStandardAuthorOlatLoginInfos(2).getUsername()}; + groupAdmin1.addMembers(new String[0], owners); + groupAdmin1.close(nameOfGroup); + + //browser 2 + GroupAdmin groupAdmin2 = workflow2.getGroups().selectGroup(nameOfGroup).selectAdministration(); + assertTrue(groupAdmin2.isChatSelected()); + groupAdmin2.setTools(false, false, false, false, false, true, false); + groupAdmin2.close(nameOfGroup); + + //browser 1 + groupAdmin1 = workflow1.getGroups().selectGroup(nameOfGroup).selectAdministration(); + assertTrue(groupAdmin1.isWikiSelected()); + + } + +} diff --git a/src/test/java/org/olat/test/functional/group/management/ConcurrentEnrolmentTest.java b/src/test/java/org/olat/test/functional/group/management/ConcurrentEnrolmentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c4aecc37e9309257411de0cee6ce80ec537d1728 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/ConcurrentEnrolmentTest.java @@ -0,0 +1,142 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; + +/** + * + * Tests if subscription to a learning group with just one place is locked if many students enrol simultaneously. + * <br/> + * Test setup: <br/> + * 1. Delete all learning groups from authors and students. <br/> + * 2. Create five student test users. <br/> + * <p> + * Test case: <br/> + * 1. Author goes to learning resources and creates course COURSE_NAME. <br/> + * 2. Author goes to group management and creates learning group "learning group selenium 5". <br/> + * 3. Author configures group to allow just one member and no waiting list. <br/> + * 4. Author opens course editor, adds course element enrolment and selects the above created group. <br/> + * 5. Author publishes course. <br/> + * 6. All five students log in and start course COURSE_NAME, navigate to enrolment course element. <br/> + * 7. Check that only one student gets into group, all other four get appropriate error message that + * group is already full. <br/> + * 8. Author deletes course. <br/> + * + * @author sandra + * + */ + +public class ConcurrentEnrolmentTest extends BaseSeleneseTestCase { + + + protected com.thoughtworks.selenium.Selenium seleniums[] = new com.thoughtworks.selenium.Selenium[5]; + private final static String COURSE_NAME = "Course_for_Enrolment_Concurrency" + System.currentTimeMillis(); + + public void testConcurrentEnrolmentTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(2, "enrolstudi02", standardPassword, true, false, false, false, false); + OlatLoginInfos student03= context.createuserIfNotExists(1, "enrolstudi03", standardPassword, true, false, false, false, false); + OlatLoginInfos student04= context.createuserIfNotExists(2, "enrolstudi04", standardPassword, true, false, false, false, false); + OlatLoginInfos student05= context.createuserIfNotExists(1, "enrolstudi05", standardPassword, true, false, false, false, false); + + + // Author01 creates course with learning group (max 1 participant) and enrolment course element + System.out.println("logging in browser 1..."); + OLATWorkflowHelper olatWorkflow_0 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources_0 = olatWorkflow_0.getLearningResources(); + LRDetailedView lRDetailedView_0 = learningResources_0.createResource(COURSE_NAME, "Enrolment Test", LR_Types.COURSE); + CourseRun courseRun_0 = learningResources_0.searchAndShowMyCourseContent(COURSE_NAME); + GroupManagement groupManagement_0 = courseRun_0.getGroupManagement(); + groupManagement_0.createLearningGroup("learning group selenium 5", "fifth lg", 1, false, false); + courseRun_0 = groupManagement_0.close(); + CourseEditor courseEditor_0 = courseRun_0.getCourseEditor(); + EnrolmentEditor enrollmentElement_0 = (EnrolmentEditor)courseEditor_0.insertCourseElement(CourseEditor.CourseElemTypes.ENROLMENT, true, null); + enrollmentElement_0.selectLearningGroups("learning group selenium 5"); + courseEditor_0.publishCourse(); + courseEditor_0.closeToCourseRun(); + olatWorkflow_0.logout(); + + // student01 opens course and navigates to enrolment course element + courseRun_0 = this.selectEnrolment(context.getStandardStudentOlatLoginInfos(1), COURSE_NAME); + + // student02 opens course and navigates to enrolment course element + System.out.println("logging in browser 2..."); + CourseRun courseRun_1 = this.selectEnrolment(student02, COURSE_NAME); + + // student03 opens course and navigates to enrolment course element + System.out.println("logging in browser 3..."); + CourseRun courseRun_2 = this.selectEnrolment(student03, COURSE_NAME); + + // student04 opens course and navigates to enrolment course element + System.out.println("logging in browser 4..."); + CourseRun courseRun_3 = this.selectEnrolment(student04, COURSE_NAME); + + // student05 opens course and navigates to enrolment course element + System.out.println("logging in browser 5..."); + CourseRun courseRun_4 = this.selectEnrolment(student05, COURSE_NAME); + + // All students enrol, only student01 should get into group + seleniums[0] = courseRun_0.getSelenium(); + seleniums[1] = courseRun_1.getSelenium(); + seleniums[2] = courseRun_2.getSelenium(); + seleniums[3] = courseRun_3.getSelenium(); + seleniums[4] = courseRun_4.getSelenium(); + + seleniums[0].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[1].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[2].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[3].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + seleniums[4].click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 5)"); + + int numWinners = 0; + int numLoosers = 0; + for(int i=0; i<5; i++) { + seleniums[i].waitForPageToLoad("30000"); + if (seleniums[i].isTextPresent("enrolled")) { + numWinners++; + } else if (seleniums[i].isTextPresent("In the meantime this group is complete. Please select another one.")) { + numLoosers++; + } else { + fail("oups..."); + } + } + assertEquals("expected only 1 winner", 1, numWinners); + assertEquals("expected only 4 loosers", 4, numLoosers); + } + + private CourseRun selectEnrolment(OlatLoginInfos student, String courseName) { + Context context = Context.getContext(); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(student); + CourseRun courseRun = olatWorkflow.getLearningResources().searchAndShowCourseContent(courseName); + courseRun.selectCourseElement(CourseEditor.ENROLMENT_TITLE); + return courseRun; + } + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + //author01 deletes course + Context context = Context.getContext(); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LRDetailedView lRDetailedView = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME); + try { + lRDetailedView.deleteLR(); + } catch (Exception e) {} + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } + +} diff --git a/src/test/java/org/olat/test/functional/group/management/ConcurrentVisibilityTest.java b/src/test/java/org/olat/test/functional/group/management/ConcurrentVisibilityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..15664f61253df47ace486a4278d0da27d449466e --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/ConcurrentVisibilityTest.java @@ -0,0 +1,113 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.StructureElement; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; + +/** + * + * Tests if group dependent visibility restrictions on course elements work depending on group membership. + * <br/> + * Test setup: <br/> + * 1. Delete all learning resources from author. <br/> + * <p> + * Test case: <br/> + * 1. Author goes to learning resources and creates course COURSE_TITLE. <br/> + * 2. Author goes to group management and creates learning group GROUP_NAME. <br/> + * 3. Author adds student 1 as participant and student 2 as tutor to group. <br/> + * 4. Author opens course editor, adds folder course element and restricts visibility to above created group. <br/> + * 5. Author publishes course. <br/> + * 6. Student 1 opens course COURSE_TITLE and navigates to folder. <br/> + * 7. Student 2 opens course COURSE_TITLE, opens group management and removes student 1 from group. <br/> + * 8. Student 1 tries to access folder but as access rights have altered gets back to course root element. <br/> + * 9. Author deletes course COURSE_TITLE. <br/> + * + * @author sandra + * + */ + +public class ConcurrentVisibilityTest extends BaseSeleneseTestCase { + + private final String COURSE_TITLE = "Course_for_Enrolment_Concurrency2-"+System.currentTimeMillis(); + private final String GROUP_NAME = "learning group selenium 6"; + private final String STUDENT_USER_NAME = "srenrolstudi03"; + + + public void testConcurrentVisibility() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(2).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(1, STUDENT_USER_NAME, standardPassword, true, false, false, false, false); + + { + // Author01 add learning group to course COURSE_TITLE, adds student01 + // as tutor and enrolmentstudent02 as participant and adds folder with visibility restriction to this group + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + System.out.println("logging in browser 1..."); + LearningResources learningResources = olatWorkflow.getLearningResources(); + learningResources.createResource(COURSE_TITLE, "Enrolment Test", LR_Types.COURSE); + LRDetailedView lRDetailedView = learningResources.searchMyResource(COURSE_TITLE); + CourseRun courseRun = lRDetailedView.showCourseContent(); + courseRun.getGroupManagement().createGroupAndAddMembers(GROUP_NAME, context.getStandardStudentOlatLoginInfos(2).getUsername(), STUDENT_USER_NAME); + CourseEditor courseEditor = courseRun.getCourseEditor(); + CourseElementEditor courseElementEditor = courseEditor.insertCourseElement(CourseElemTypes.FOLDER, true, null); + courseElementEditor.changeVisibilityDependingOnGroup(GROUP_NAME); + courseEditor.publishCourse(); + courseEditor.closeToCourseRun(); + olatWorkflow.logout(); + } + + //enrolmentstudent02 opens course and navigates to folder + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(student02); + CourseRun courseRun1 = olatWorkflow1.getLearningResources().searchAndShowCourseContent(COURSE_TITLE); + courseRun1.selectCourseElement("Folder"); + + // student01 opens course, then group administration and removes + // enrolmentstudent02 from group + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + CourseRun courseRun2 = olatWorkflow2.getLearningResources().searchAndShowCourseContent(COURSE_TITLE); + Thread.sleep(3000); + courseRun2.removeFromTutoredGroup(GROUP_NAME, STUDENT_USER_NAME); + + + // enrolmentstudent02 should not be able to select the folder node anymore: + //when the user attempts to select the node the root gets selected and the user gets a accessRightAltered message + /*courseRun1.selectCourseElement("Folder"); + selenium1 = courseRun1.getSelenium();*/ + StructureElement root = courseRun1.selectAnyButGetToRoot("Folder"); + + boolean accessRightAltered = false; + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { + if (root.getSelenium().isTextPresent("Your access rights have been altered in the meantime. Therefore you cannot select the course element required anymore.")) { + accessRightAltered = true; + break; } + } catch (Exception e) {} + Thread.sleep(1000); + + } + assertTrue("Asserts that the access rights message shows up",accessRightAltered); + + } + + @Override + protected void cleanUpAfterRun() { + //author01 deletes course + OLATWorkflowHelper olatWorkflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources = olatWorkflow.getLearningResources(); + learningResources.searchMyResource(COURSE_TITLE).deleteLR(); + } + + +} diff --git a/src/test/java/org/olat/test/functional/group/management/ConfigureToolsLearningGroup.java b/src/test/java/org/olat/test/functional/group/management/ConfigureToolsLearningGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..22f7a68fd4697adbc729140680c4037133e022a3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/ConfigureToolsLearningGroup.java @@ -0,0 +1,89 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.group.Group; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.home.Home; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Adds all collaborative tools to learning group and checks their configuration, part of test suite GroupManagementCombiTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Authors goes to learning resources and opens course COURSE_NAME. <br/> + * 2. Author opens group management and edits group GROUP_NAME_1. <br/> + * 3. Author configures group tools to info on, contact form on, calendar on, folder on, forum on, wiki on, chat off. <br/> + * 4. Author edits group info message. <br/> + * 5. Author starts group and writes forum message. <br/> + * 6. Student selects group GROUP_NAME_1 from Home - My groups. <br/> + * 7. Student checks if info message is present. <br/> + * 8. Student replies to forum message. <br/> + * 9. Student checks if he can see members.<br/> + * 10. Student checks if calendar is present. <br/> + * 11. Student starts course and checks if enrolment course element is present. <br/> + * + * @author sandra + * + */ + + +public class ConfigureToolsLearningGroup extends BaseSeleneseTestCase { + + @Test(dependsOnGroups={GroupManagementCombiTest.SECOND}) + public void testConfigureToolsLearningGroupTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(1, GroupManagementCombiTest.STUDENT_USER_NAME, standardPassword, true, false, false, false, false); + + // refactored with abstraction layer + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources1 = olatWorkflow1.getLearningResources(); + LRDetailedView lRDetailedView1 = learningResources1.searchMyResource(GroupManagementCombiTest.COURSE_NAME); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + GroupAdmin groupAdmin1 = courseRun1.getGroupManagement().editLearningGroup(GroupManagementCombiTest.GROUP_NAME_1); + groupAdmin1.setTools(true, true, true, true, true, true, false); + groupAdmin1.setInfo("hello everybody"); + Thread.sleep(5000); + groupAdmin1.setMemberDisplayOptions(null, true, null); + Thread.sleep(5000); + Group group1 = groupAdmin1.start(GroupManagementCombiTest.GROUP_NAME_1); + Thread.sleep(5000); + Forum forum1 = group1.selectForum(); + forum1.openNewTopic("welcome", "welcome everybody"); + olatWorkflow1.logout(); + + // log in student02 + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(student02); + Home home1 = olatWorkflow2.getHome(); + Group group2 = home1.selectMyGroup(GroupManagementCombiTest.GROUP_NAME_1); + group2.selectInfo(); + assertTrue(group2.isTextPresent("hello everybody")); + Forum forum2 = group2.selectForum(); + Thread.sleep(10000); + forum2.replyToTopic("welcome", "my reply", false); + group2.selectMembers(); + assertTrue(group2.isTextPresent(GroupManagementCombiTest.STUDENT_USER_NAME)); + assertTrue(group2.isTextPresent("srlgauthor02")); + group2.selectCalendar(); + group2.startCourse(); + assertTrue(group2.isTextPresent("Course element of the type Enrolment")); + olatWorkflow2.logout(); + + } + + +} + diff --git a/src/test/java/org/olat/test/functional/group/management/CreateLearningGroupLearningArea.java b/src/test/java/org/olat/test/functional/group/management/CreateLearningGroupLearningArea.java new file mode 100644 index 0000000000000000000000000000000000000000..2e30f56d9c90cc784ab6e906a20d144d87f92c24 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/CreateLearningGroupLearningArea.java @@ -0,0 +1,101 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.group.LearningArea; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Checks if enrolment course element with learning groups and learning areas works, part of test suite GroupManagementCombiTest.java. + * <br/> + * Test setup: <br/> + * 1. Delete all learning resources and groups from author. <br/> + * 2. Create user "srlgauthor02". <br/> + * <p> + * Test case: <br/> + * 1. Author creates course COURSE_NAME. <br/> + * 2. Author switches to course run, opens group management and creates group GROUP_NAME_1. <br/> + * 3. Author adds "srlgauthor02" to group. <br/> + * 5. Author closes group management and opens course editor. <br/> + * 6. Author adds enrolment course element and adds group GROUP_NAME_1. <br/> + * 7. Author publishes course. <br/> + * 8. Author closes editor, opens group management. <br/> + * 9. Author creates learning area "learning area selenium 1" and two groups, adds these two groups to learning area. <br/> + * 10. Author closes group management and opens course editor. <br/> + * 11. Author adds another course element enrolment "enrolment learning areas" and adds "learning area selenium 1". <br/> + * 12. Author publishes course and logs out. <br/> + * 13. Standard student opens course COURSE_NAME and navigates to "enrolment learning areas". <br/> + * 14. Student checks if the two groups are available. <br/> + * + * @author sandra + * + */ + +public class CreateLearningGroupLearningArea extends BaseSeleneseTestCase { + + @Test(groups = {GroupManagementCombiTest.FIRST}) + public void testCreateLearningGroupLearningAreaTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // delete all author's groups first !!! + WorkflowHelper.deleteAllGroupsFromAuthor(context.getStandardAuthorOlatLoginInfos(1)); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + // TODO this user is never used, line could be deleted. + OlatLoginInfos author02= context.createuserIfNotExists(1, "srlgauthor02", standardPassword, true, false, false, false, false); + + // refactored with abstraction layer + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LearningResources learningResources1 = olatWorkflow1.getLearningResources(); + LRDetailedView lRDetailedView1 = learningResources1.createResource(GroupManagementCombiTest.COURSE_NAME, "GroupAdmin Management Test", LR_Types.COURSE); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + GroupAdmin group1 = courseRun1.getGroupManagement().createLearningGroup(GroupManagementCombiTest.GROUP_NAME_1, "first lg", 2, true, true); + assertFalse("Could not create group. It was already there: learning group selenium 1", group1.isTextPresent("This group name is already being used in this context, please select another one.")); + String[] userNames = {"srlgauthor02", context.getStandardStudentOlatLoginInfos(1).getUsername()}; + group1.addMembers(userNames, new String[0]); + courseRun1 = courseRun1.getGroupManagement().close(); + CourseEditor courseEditor1 = courseRun1.getCourseEditor(); + EnrolmentEditor enrolmentElement1 = (EnrolmentEditor)courseEditor1.insertCourseElement(CourseElemTypes.ENROLMENT, true, null); + enrolmentElement1.selectLearningGroups(GroupManagementCombiTest.GROUP_NAME_1); + courseEditor1.publishCourse(); + courseRun1 = courseEditor1.closeToCourseRun(); + GroupManagement groupManagement1 = courseRun1.getGroupManagement(); + groupManagement1.createLearningArea("learning area selenium 1", "area description"); + groupManagement1.createLearningGroup("learning group selenium 2", "description 2", 0, false, false); + groupManagement1.createLearningGroup("learning group selenium 3", "description 3", 0, false, false); + LearningArea learningArea1 = groupManagement1.editLearningArea("learning area selenium 1"); + String[] groupNames = {"learning group selenium 2", "learning group selenium 3"}; + learningArea1.assignGroup(groupNames); + courseRun1 = groupManagement1.close(); + courseEditor1 = courseRun1.getCourseEditor(); + enrolmentElement1 = (EnrolmentEditor)courseEditor1.insertCourseElement(CourseElemTypes.ENROLMENT, true, "Enrolment learning areas"); + enrolmentElement1.selectLearningAreas("learning area selenium 1"); + courseEditor1.publishCourse(); + courseEditor1.closeToCourseRun(); + olatWorkflow1.logout(); + + + // student logs in and checks if enrolment works as expected: should be fine like that + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + LearningResources learningResources2 = olatWorkflow2.getLearningResources(); + CourseRun courseRun2 = learningResources2.searchAndShowCourseContent(GroupManagementCombiTest.COURSE_NAME); + courseRun2.selectCourseElement("Enrolment learning areas"); + assertTrue(courseRun2.isTextPresent("learning group selenium 2")); + assertTrue(courseRun2.isTextPresent("learning group selenium 3")); + olatWorkflow2.logout(); + } +} diff --git a/src/test/java/org/olat/test/functional/group/management/EnrollmentWithSizeLimitationTest.java b/src/test/java/org/olat/test/functional/group/management/EnrollmentWithSizeLimitationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6ee95e656f5c990062ced953cb0a2bf6e08afa52 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/EnrollmentWithSizeLimitationTest.java @@ -0,0 +1,141 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Test Jira Issue OLAT-5022: <br/> + * define a learning group with a place limitation (assert that the place + limitation is saved), waiting list and automatic adding. Add users until the group is full, remove + one user, assert that the first on the waiting list is included in the group + * <br/> + * </p> + * Test case: <br/> + * create groupWithLimitation <br/> + * define a learning group with a place limitation <br/> + * open course editor <br/> + * insert enrolment element <br/> + * publish and close <br/> + * author enrolls in groupWithLimitation <br/> + * assert -> author is enrolled! <br/> + * student tries to enroll in groupWithLimitation that is already full! <br/> + * student opens course and navigates to enrollment course element <br/> + * assert -> student is on waiting list! <br/> + * author cancels enrollment <br/> + * assert author enrollment was canceled <br/> + * assert -> student is now enrolled! <br/> + * Delete groups <br/> + * Test the same adding several groups separated with a comma at one time <br/> + * Delete course <br/> + * + * @author alberto + */ +public class EnrollmentWithSizeLimitationTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + public void testEnrolmentWaitingList() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + + OLATWorkflowHelper olatWorkflow_0 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + + // author creates course with learning group (max 1 participant) and enrollment course element + + LearningResources learningResources_0 = olatWorkflow_0.getLearningResources(); + LRDetailedView lRDetailedView_0 = learningResources_0.createResource(COURSE_NAME, "Enrolment Test", LR_Types.COURSE); + CourseRun courseRun_0 = learningResources_0.searchAndShowMyCourseContent(COURSE_NAME); + + //create groupWithLimitation + GroupManagement groupManagement_0 = courseRun_0.getGroupManagement(); + GroupAdmin groupAdmin = groupManagement_0.createLearningGroup("groupWithLimitation", "group description", 1, true, true); + //assert that the place limitation is saved + assertTrue(groupAdmin.getMaxNumParticipants().equals("1"));; + courseRun_0 = groupManagement_0.close(); + + //open course editor + CourseEditor courseEditor_0 = courseRun_0.getCourseEditor(); + + //insert enrollment element + EnrolmentEditor enrollmentElement_0 = (EnrolmentEditor)courseEditor_0.insertCourseElement(CourseEditor.CourseElemTypes.ENROLMENT, true, null); + enrollmentElement_0.selectLearningGroups("groupWithLimitation"); + + //publish and close + courseEditor_0.publishCourse(); + courseEditor_0.closeToCourseRun(); + olatWorkflow_0.logout(); + + // author enrolls in groupWithLimitation + courseRun_0 = this.selectEnrolment(context.getStandardAuthorOlatLoginInfos(1), COURSE_NAME); + EnrolmentRun enrolmentRun_0 = courseRun_0.selectEnrolment("Enrolment"); + enrolmentRun_0.enrol("groupWithLimitation"); + + // assert -> author is enrolled! + //assertTrue(courseRun_0.isTextPresent("enrolled")); + + assertTrue(enrolmentRun_0.alreadyEnrolled("groupWithLimitation")); + + + // student opens course and navigates to enrollment course element + CourseRun courseRun_1 = this.selectEnrolment(context.getStandardStudentOlatLoginInfos(1), COURSE_NAME); + EnrolmentRun enrolmentRun_1 = courseRun_1.selectEnrolment("Enrolment"); + + + + // student tries to enroll in groupWithLimitation that is already full! + enrolmentRun_1.enrol("groupWithLimitation"); + + // assert -> student is on waiting list! + assertTrue(enrolmentRun_1.isTextPresent("On waiting list (1)")); + + // author cancels enrollment + enrolmentRun_0.cancelEnrolment("groupWithLimitation"); + + // assert author enrollment was canceled + assertTrue(courseRun_0.isTextPresent("Choose one of the learning groups below to enrol")); + + // assert -> student is now enrolled! + enrolmentRun_1 = courseRun_1.selectEnrolment("Enrolment"); + assertTrue(enrolmentRun_1.alreadyEnrolled("groupWithLimitation")); + + + } + private CourseRun selectEnrolment(OlatLoginInfos student, String courseName) { + Context context = Context.getContext(); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(student); + CourseRun courseRun = olatWorkflow.getLearningResources().searchAndShowCourseContent(courseName); + courseRun.selectCourseElement(CourseEditor.ENROLMENT_TITLE); + return courseRun; + } + + + + @Override + protected void cleanUpAfterRun() { + System.out.println("***************** cleanUpAfterRun STARTED *********************"); + //author01 deletes course + Context context = Context.getContext(); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + LRDetailedView lRDetailedView = olatWorkflow.getLearningResources().searchMyResource(COURSE_NAME); + try { + lRDetailedView.deleteLR(); + } catch (Exception e) {} + System.out.println("***************** cleanUpAfterRun ENDED *********************"); + } + +} diff --git a/src/test/java/org/olat/test/functional/group/management/EnrolmentLearningGroup.java b/src/test/java/org/olat/test/functional/group/management/EnrolmentLearningGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..dd090f51631a926637e78b4695b5b52e0653d203 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/EnrolmentLearningGroup.java @@ -0,0 +1,66 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.home.Home; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Student subscribes to waiting list and moves up to regular group member when other student cancels his enrolment, part of test suite GroupManagementCombiTest.java. + * <br/> + * Test setup: <br/> + * 1. Student 2 is already member of learning group (from test case CreateLearningGroupLearningArea.java) + * <p> + * Test case: <br/> + * 1. Student 1 opens course COURSE_NAME, sets bookmark and navigates to enrolment course element. <br/> + * 2. Student 1 enrols and checks if he is on waiting list. <br/> + * 3. Student 2 opens course COURSE_NAME and navigates to same enrolment course element. <br/> + * 5. Student 2 cancels enrolment. <br/> + * 6. Student 1 goes to enrolment again and checks if he has moved from waiting list to enrolled member. <br/> + * + * @author sandra + * + */ + +public class EnrolmentLearningGroup extends BaseSeleneseTestCase { + + @Test(dependsOnGroups = {GroupManagementCombiTest.FIRST}, groups = {GroupManagementCombiTest.SECOND}) + public void testEnrolmentLearningGroupTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos student02= context.createuserIfNotExists(1, GroupManagementCombiTest.STUDENT_USER_NAME, standardPassword, true, false, false, false, false); + + // refactored with abstraction layer + OLATWorkflowHelper workflow1 = context.getOLATWorkflowHelper(student02); + LearningResources learningResources1 = workflow1.getLearningResources(); + CourseRun courseRun1 = learningResources1.searchAndShowCourseContent(GroupManagementCombiTest.COURSE_NAME); + courseRun1.setBookmark(); + EnrolmentRun enrolmentRun1 = courseRun1.selectEnrolment("Enrolment"); + enrolmentRun1.enrol(GroupManagementCombiTest.GROUP_NAME_1); + assertTrue(enrolmentRun1.isTextPresent("On waiting list (1)")); + workflow1.logout(); + + OLATWorkflowHelper workflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + LearningResources learningResources2 = workflow2.getLearningResources(); + CourseRun courseRun2 = learningResources2.searchAndShowCourseContent(GroupManagementCombiTest.COURSE_NAME); + EnrolmentRun enrolmentRun2 = courseRun2.selectEnrolment("Enrolment"); + enrolmentRun2.cancelEnrolment(GroupManagementCombiTest.GROUP_NAME_1); + workflow2.logout(); + + OLATWorkflowHelper workflow3 = context.getOLATWorkflowHelper(student02); + Home home1 = workflow3.getHome(); + CourseRun courseRun3 = home1.selectMyBookmarkedCourse(GroupManagementCombiTest.COURSE_NAME); + courseRun3.selectCourseElement("Enrolment"); + assertTrue(courseRun3.isTextPresent("enrolled")); + workflow3.logout(); + + } +} diff --git a/src/test/java/org/olat/test/functional/group/management/EnrolmentWaitinglistTest.java b/src/test/java/org/olat/test/functional/group/management/EnrolmentWaitinglistTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2dbba98265943948f5c455b3b2c40e2b665dcbb9 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/EnrolmentWaitinglistTest.java @@ -0,0 +1,122 @@ +package org.olat.test.functional.group.management; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests Enrolment and Waitinglist with 3 participants + * Original name: MultiBrowserClusterEnrolmentWaitinglistTest + * <br/> + * <p> + * Test case: <br/> + * make sure the limit on participants on group A is 1 <br/> + * go to group management and modify the limit on gruppe A to 1 <br/> + * log in user 2 and 3 <br/> + * user 1 does an enrolment to gruppe A <br/> + * user 2 does a enrol too but lands on the waitinglist <br/> + * user 3 and the admin in parallel (which is played by selenium1) <br/> + * user 3 does an enrol <br/> + * admin deletes user 1 from the course <br/> + * now in 'parallel' <br/> + * make the asserts <br/> + * + * </p> + * + * @author eglis + * + */ +public class EnrolmentWaitinglistTest extends BaseSeleneseTestCase { + + + + private OLATWorkflowHelper workflow1; + private CourseRun courseRun1; + + private OLATWorkflowHelper workflow2; + private CourseRun courseRun2; + + private OLATWorkflowHelper workflow3; + + private final String COURSE_NAME = Context.DEMO_COURSE_NAME_3; + private final String GROUP_NAME = "Gruppe A"; + private final String ENROLMENT_ELEMENT = "Einschreibung"; + + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos user1 = context.createuserIfNotExists(1, "enrtstusr1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(1, "enrtstusr2", standardPassword, true, true, true, true, true); + OlatLoginInfos user3 = context.createuserIfNotExists(2, "enrtstusr3", standardPassword, true, true, true, true, true); + + // step1: make sure the limit on participants on group A is 1 + { + System.out.println("logging in browser 1..."); + workflow1 = context.getOLATWorkflowHelper(user1); + courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + // go to group management and modify the limit on gruppe A to 1 + GroupAdmin groupAdmin = courseRun1.getGroupManagement().editLearningGroup(GROUP_NAME); + groupAdmin.removeAllWaiting(); + groupAdmin.removeAllParticipants(); + groupAdmin.configureParticipantsAndWaitingList(1, Boolean.TRUE, Boolean.TRUE); + groupAdmin.close(GROUP_NAME); + courseRun1.close(COURSE_NAME); + } + + // step 2: log in user 2 and 3 + { + System.out.println("logging in browser 2..."); + workflow2 = context.getOLATWorkflowHelper(user2); + } + { + System.out.println("logging in browser 3..."); + workflow3 = context.getOLATWorkflowHelper(user3); + } + + // step 3: user 1 does an enrolment to gruppe A + { + CourseRun courseRun = workflow1.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun = courseRun.selectEnrolment(ENROLMENT_ELEMENT); + enrolmentRun.enrol(GROUP_NAME); + assertTrue(enrolmentRun.isTextPresent("You have already enroled for the learning group mentioned below")); + } + + // step 4: user 2 does a enrol too but lands on the waitinglist + { + courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(COURSE_NAME); + EnrolmentRun enrolmentRun2 = courseRun2.selectEnrolment(ENROLMENT_ELEMENT); + enrolmentRun2.enrol(GROUP_NAME); + assertTrue(enrolmentRun2.isTextPresent("You are on the waiting list of the learning group mentioned below")); + } + + // step 5: user 3 and the admin in parallel (which is played by selenium1): + // user 3 does an enrol + // admin deletes user 1 from the course + { + // admin: + GroupAdmin groupAdmin1 = courseRun1.getGroupManagement().editLearningGroup(GROUP_NAME); + groupAdmin1.removeParticipant("enrtstusr1", false); + // selenium1.click("ui=dialog::Yes()"); .. but we wait with that + + EnrolmentRun enrolmentRun3 = workflow3.getLearningResources().searchAndShowCourseContent(COURSE_NAME).selectEnrolment(ENROLMENT_ELEMENT); + // selenium3.click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=Gruppe A)"); .. but we wait with that + + // now in 'parallel': + groupAdmin1.confirmRemove(); + enrolmentRun3.enrol(GROUP_NAME); + + // make the asserts: + assertTrue(enrolmentRun3.isTextPresent("You are on the waiting list of the learning group mentioned below")); + courseRun2.selectEnrolment(ENROLMENT_ELEMENT); + assertTrue(courseRun2.isTextPresent("You have already enroled for the learning group mentioned below")); + } + + } +} diff --git a/src/test/java/org/olat/test/functional/group/management/GroupManagementCombiTest.java b/src/test/java/org/olat/test/functional/group/management/GroupManagementCombiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1f269bd2527206984be775f0b1f56937a8b0d8a9 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/GroupManagementCombiTest.java @@ -0,0 +1,47 @@ +package org.olat.test.functional.group.management; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * + * Combi test for group management. See respective test classes for extensive documentation. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. CreateLearningGroupLearningArea.java checks if enrolment course element with learning groups and learning areas works. <br/> + * 2. EnrolmentLearningGroup.java checks if student subscribed to waiting list moves up to regular group member when other student cancels his enrolment. <br/> + * 3. ConfigureToolsLearningGroup adds all collaborative tools to learning group and checks their configuration.<br/> + * + * @author sandra + * + */ + +public class GroupManagementCombiTest extends TestSuite { + + protected final static String COURSE_NAME = "Course_for_Group_Management" + System.currentTimeMillis(); + protected final static String GROUP_NAME_1 = "learning group selenium 1"; + + + + final static String FIRST = "GroupManagementCombiTest.FIRST"; + final static String SECOND = "GroupManagementCombiTest.SECOND"; + + //seleniumload: make sure that this is not a user with reusable urls!!! + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + //protected final static String STUDENT_USER_NAME = "srenrolstudi_02"; + protected final static String STUDENT_USER_NAME = "srenrolstudi02"; + + public static Test suite() { + TestSuite suite = new TestSuite("CombiTest"); + + suite.addTestSuite(CreateLearningGroupLearningArea.class); + suite.addTestSuite(EnrolmentLearningGroup.class); + suite.addTestSuite(ConfigureToolsLearningGroup.class); + + return suite; + } + +} diff --git a/src/test/java/org/olat/test/functional/group/management/MultiBrowserClusterUpdateLearningAreaTstDisabled3444.java b/src/test/java/org/olat/test/functional/group/management/MultiBrowserClusterUpdateLearningAreaTstDisabled3444.java new file mode 100644 index 0000000000000000000000000000000000000000..9e4b2232b4a2876ad5ea175e90ae9550953534e1 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/MultiBrowserClusterUpdateLearningAreaTstDisabled3444.java @@ -0,0 +1,106 @@ +package org.olat.test.functional.group.management; + +import org.junit.Ignore; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +@Ignore +public class MultiBrowserClusterUpdateLearningAreaTstDisabled3444 extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos user1 = context.createuserIfNotExists(1, "mbcnla1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "mbcnla2", standardPassword, true, true, true, true, true); + + { + System.out.println("logging in browser 1..."); + selenium1 = context.createSeleniumAndLogin(user1); + selenium1.click("ui=tabs::learningResources()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::menu_searchForm()"); + selenium1.waitForPageToLoad("30000"); + selenium1.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium1.click("ui=learningResources::content_searchForm_search()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=learningResources::content_showContent()"); + selenium1.waitForPageToLoad("30000"); + + selenium1.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium1.waitForPageToLoad("30000"); + + // make sure the learning area does not exist yet - delete otherwise + selenium1.click("ui=groupManagement::menu_allLearningAreas()"); + selenium1.waitForPageToLoad("30000"); + if (selenium1.isElementPresent("ui=groupManagement::content_learningAreaTable_deleteLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)")) { + selenium1.click("ui=groupManagement::content_learningAreaTable_deleteLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=dialog::Yes()"); + selenium1.waitForPageToLoad("30000"); + } + + // create the learning area + selenium1.click("ui=groupManagement::toolbox_groupManagement_newLearningArea()"); + selenium1.waitForPageToLoad("30000"); + assertTrue(selenium1.isTextPresent("Create a new learning area")); + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", "multibrowserclusterlearningarea"); + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_description()", "egal oder?"); + selenium1.click("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()"); + selenium1.waitForPageToLoad("30000"); + + // open the learning area in edit mode + selenium1.click("ui=groupManagement::menu_allLearningAreas()"); + selenium1.waitForPageToLoad("30000"); + selenium1.click("ui=groupManagement::content_learningAreaTable_editLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)"); + selenium1.waitForPageToLoad("30000"); + + // edit the title + selenium1.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", "mod1"); + } + + { + System.out.println("logging in browser 2..."); + selenium2 = context.createSeleniumAndLogin(user2); + selenium2.click("ui=tabs::learningResources()"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::menu_searchForm()"); + selenium2.waitForPageToLoad("30000"); + selenium2.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium2.click("ui=learningResources::content_searchForm_search()"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=learningResources::content_showContent()"); + selenium2.waitForPageToLoad("30000"); + + selenium2.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium2.waitForPageToLoad("30000"); + + // open the learning area in edit mode + selenium2.click("ui=groupManagement::menu_allLearningAreas()"); + selenium2.waitForPageToLoad("30000"); + selenium2.click("ui=groupManagement::content_learningAreaTable_editLearningArea(nameOfLearningArea=multibrowserclusterlearningarea)"); + selenium2.waitForPageToLoad("30000"); + + // edit the title + selenium2.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", "mod2"); + } + + selenium1.click("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()"); + selenium2.click("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()"); + + selenium1.waitForPageToLoad("30000"); + selenium2.waitForPageToLoad("30000"); + + assertTrue("Not found in selenium 1: Edit learning area multibrowserclusterlearningarea", selenium1.isTextPresent("Edit learning area multibrowserclusterlearningarea")); + assertTrue("Not found in selenium 2: Edit learning area multibrowserclusterlearningarea", selenium2.isTextPresent("Edit learning area multibrowserclusterlearningarea")); + } +} diff --git a/src/test/java/org/olat/test/functional/group/management/concurrent_visibility.html b/src/test/java/org/olat/test/functional/group/management/concurrent_visibility.html new file mode 100644 index 0000000000000000000000000000000000000000..4237e5fe9acdbe8d7f3bb3338b58b54614fe896a --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/concurrent_visibility.html @@ -0,0 +1,384 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>group_management_concurrencies2</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">group_management_concurrencies2</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickLearningResource(nameOfLearningResource=Course_for_Enrolment)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_learningResource_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()</td> + <td>learning group selenium 6</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_learningGroupsEditor_addMembers_addTutor()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student02</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student02)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_close()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_courseEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertFolder()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_tabVisbility()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_dependingGroup()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_selectLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=learning group selenium 6)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_visibility_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Course_for_Enrolment_Concurrency)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_folder()</td> + <td></td> +</tr> +<!--wait until student01 removes him from group--> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Course_for_Enrolment_Concurrency)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_myGroupsTools_tutoredGroups(nameOfGroup=learning group selenium 6)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_administration()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_checkUsername(nameOfUser=student02)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_remove()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dialog::Yes()</td> + <td></td> +</tr> +<!--student02--> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_folder()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Your access rights have been altered in the meantime. Therefore you cannot select the desired course element anymore.</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/group/management/configure_tools.html b/src/test/java/org/olat/test/functional/group/management/configure_tools.html new file mode 100644 index 0000000000000000000000000000000000000000..bd71313d4193cf3ebf4e5b2efdd41a580a436dc3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/configure_tools.html @@ -0,0 +1,297 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>configure_tools_neu</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">configure_tools_neu</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/?o_winrndo=1</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Course_for_Group_Management)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::menu_allLearningGroups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_learningGroupTable_editLearningGroup(nameOfLearningGroup=learning group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_tools_tabTools()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_information()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_contactForm()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_calendar()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_folder()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_forum()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_wiki()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_tools_collaborationTools_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_informationForMembers_formFieldInformationMembers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=group::content_tools_informationForMembers_formFieldInformationMembers()</td> + <td>hello everybody</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_tools_informationForMembers_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_startCourse()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_forum()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_newTopic()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::content_forum_typeMsgTitle()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_typeMsgTitle()</td> + <td>welcome</td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td>welcome everybody</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>enrolmentstudent02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat2</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=home::content_portlets_myGroups(nameOfGroup=learning group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_information()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>hello everybody</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_forum()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_viewTopic(nameOfTopic=welcome)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_replyWithoutQuotation()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=course::content_forum_clickMsgBody()</td> + <td>my reply</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_forum_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_calendar()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_members()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>enrolmentstudent02</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>testauthor02</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_course()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_startCourse()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Course element of the type Enrolment</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/group/management/create_learning_group_learning_area.html b/src/test/java/org/olat/test/functional/group/management/create_learning_group_learning_area.html new file mode 100644 index 0000000000000000000000000000000000000000..71bbf6b73bec7ddb56ea90c2c7703f36426e2fe4 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/create_learning_group_learning_area.html @@ -0,0 +1,537 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>group_management_create_learning_group_learning_area</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">group_management_create_learning_group_learning_area</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_course()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>Course_for_Group_Management</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_description()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>Group Management Test</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startNo()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=Course_for_Group_Management)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()</td> + <td>learning group selenium 1</td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_description()</td> + <td>first lg</td> +</tr> +<tr> + <td>click</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_enableWaitinglist()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_maxParticipants()</td> + <td>2</td> +</tr> +<tr> + <td>click</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_moveUpAutomatically()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>author02</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=author02)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_close()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_courseEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertEnrolment()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_tabConfiguration()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=learning group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_groupManagement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningArea()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()</td> + <td>learning area selenium 1</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningArea_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()</td> + <td>learning group selenium 2</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_newLearningGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()</td> + <td>learning group selenium 3</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::menu_allLearningAreas()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_learningAreaTable_editLearningArea(nameOfLearningArea=learning area selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_learningAreaEditor_tabs_groupAssignment()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=groupManagement::content_learningAreaEditor_groupAssignment_checkLearningGroup(nameOfGroup=learning group selenium 2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=groupManagement::content_learningAreaEditor_groupAssignment_checkLearningGroup(nameOfGroup=learning group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::content_learningAreaEditor_groupAssignment_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groupManagement::toolbox_groupManagement_close()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_courseTools_courseEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertEnrolment()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=courseEditor::content_TitleDescription_shortTitle()</td> + <td>Enrolment learning areas</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_TitleDescription_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_tabConfiguration()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningArea()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=learning area selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbEnrolment_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::password()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=Course_for_Group_Management)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_learningResource_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Enrolment learning areas)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>learning group selenium 2</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>learning group selenium 3</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/group/management/createprojectgroup_add_users.html b/src/test/java/org/olat/test/functional/group/management/createprojectgroup_add_users.html new file mode 100644 index 0000000000000000000000000000000000000000..5803a770f7852f0d91a27fa1a8c6108f907a9caf --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/createprojectgroup_add_users.html @@ -0,0 +1,257 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>groups_createprojectgroup_add_users</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">groups_createprojectgroup_add_users</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>nightly</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::toolbox_create_projectGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupName()</td> + <td>project group selenium 3</td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupDescription()</td> + <td>selenium 3</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::createGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_owners_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>author02</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=author02)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td></td> + <td>project group selenium 3</td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/group/management/enrolment.html b/src/test/java/org/olat/test/functional/group/management/enrolment.html new file mode 100644 index 0000000000000000000000000000000000000000..ba1128cd2c772d795e24f7931cc7acc1858756e3 --- /dev/null +++ b/src/test/java/org/olat/test/functional/group/management/enrolment.html @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>group_management_enrolment</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">group_management_enrolment</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>nightly</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=Course_for_Group_Management)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::toolbox_generalTools_setBookmark()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Enrolment)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_enrollment_enrolOnGroup(nameOfGroup=learning group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>On waiting list (1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=Course_for_Group_Management)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Enrolment)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::content_enrollment_cancelEnrolment(nameOfGroup=learning group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>link=Course_for_Group_Management</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Enrolment)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>enrolled</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/groups/CreateProjectGroupAddUsersTest.java b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupAddUsersTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cf22000207c4f29081d5ff87459103fc21818716 --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupAddUsersTest.java @@ -0,0 +1,70 @@ +package org.olat.test.functional.groups; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * User creates course and tests case tests if he can add owner and participants. + * <br/> + * Test setup: <br/> + * 1. Clean-up: delete all groups from author + * 2. Create test user + * <p> + * Test case: <br/> + * 1. author creates group GROUP_NAME and adds users and owners + * 2. student logs in, checks if he's in GROUP_NAME and leaves GROUP_NAME + * 3. author deletes group <br/> + * + * + * @author sandra + * + */ + +public class CreateProjectGroupAddUsersTest extends BaseSeleneseTestCase { + + public void testCreateProjectGroupAddUsersTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos(1).getPassword(); + OlatLoginInfos author02= context.createuserIfNotExists(1, "testauthor02", standardPassword, true, false, false, false, false); + + // delete all my groups first !!! + WorkflowHelper.deleteAllGroupsFromAuthor(author02); + + // author creates group and adds users and owners + OLATWorkflowHelper oLATWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + Groups groupsTab = oLATWorkflowHelper.getGroups(); + GroupAdmin groupAdmin = groupsTab.createProjectGroup("project group selenium 3", "selenium 3"); + String[] owners = {"testauthor02"}; + String[] participants = {context.getStandardStudentOlatLoginInfos(1).getUsername()}; + groupAdmin.addMembers(participants, owners); + oLATWorkflowHelper.logout(); + + + //student logs in and leaves group + oLATWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + groupsTab = oLATWorkflowHelper.getGroups(); + assertFalse(groupsTab.getSelenium().isElementPresent("ui=groups::content_deleteGroup(nameOfGroup=project group selenium 3)")); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (groupsTab.getSelenium().isElementPresent("ui=groups::content_leaveGroup(nameOfGroup=project group selenium 3)")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + groupsTab.leaveGroup("project group selenium 3"); + oLATWorkflowHelper.logout(); + + + // testauthor02 deletes group + oLATWorkflowHelper = context.getOLATWorkflowHelper(author02); + oLATWorkflowHelper.getGroups().deleteGroup("project group selenium 3"); + oLATWorkflowHelper.logout(); + assertEquals("OLAT - Online Learning And Training", oLATWorkflowHelper.getSelenium().getTitle()); + } +} diff --git a/src/test/java/org/olat/test/functional/groups/CreateProjectGroupConfigureToolsTest.java b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupConfigureToolsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8ea3c050698a08622803025a0c1e8cf4af54b860 --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupConfigureToolsTest.java @@ -0,0 +1,82 @@ +package org.olat.test.functional.groups; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.group.Group; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * User creates course and configures group tools. + * <br/> + * Test setup: <br/> + * 1. Clean-up: delete all groups from author + * <p> + * Test case: <br/> + * 1. author creates group GROUP_NAME and adds student as participant.<br/> + * 2. author changes group description, activates all group tools, sets info, sets calendar writing access. <br/> + * 3. student logs in, checks if all tools are available as configured. <br/> + * 4. student leaves group.<br/> + * 5. author deletes group. <br/> + * + * @author sandra + * + */ + +public class CreateProjectGroupConfigureToolsTest extends BaseSeleneseTestCase { + + private final String GROUP_NAME_CHANGED = "project group selenium 2 changed"; + + public void testCourseOpenClose() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // delete all my groups first !!! + WorkflowHelper.deleteAllGroupsFromAuthor(context.getStandardAuthorOlatLoginInfos(1)); + + //author creates group and adds user + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + Groups groups1 = olatWorkflow1.getGroups(); + GroupAdmin group = groups1.createProjectGroup("project group selenisum 2", "second test"); + group.setTitleAndDescription(GROUP_NAME_CHANGED, "description changed"); + group.setTools(true, true, true, true, true, true, false); + group.setInfo("hello everybody"); + group.selectCalendarWriteAccess("Owners and tutors respectively"); + String[] userNames = {context.getStandardStudentOlatLoginInfos(1).getUsername()}; + group.addMembers(userNames, new String[0]); + olatWorkflow1.logout(); + + // user clicks all tools and leaves group + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + Group myGroup = olatWorkflow2.getHome().selectMyGroup(GROUP_NAME_CHANGED); + myGroup.selectInfo(); + assertTrue(myGroup.isTextPresent("hello everybody")); + myGroup.selectCalendar(); + Thread.sleep(3000); + assertTrue(myGroup.getSelenium().isElementPresent("ui=group::menu_calendar_readOnly()")); + myGroup.selectMembers(); + myGroup.selectEmail(); + myGroup.selectFolder(); + myGroup.selectWiki(); + myGroup.selectForum(); + + Groups groups2 = olatWorkflow2.getGroups(); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (groups2.getSelenium().isElementPresent("ui=groups::content_leaveGroup(nameOfGroup=" + GROUP_NAME_CHANGED + ")")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + groups2.leaveGroup(GROUP_NAME_CHANGED); + olatWorkflow2.logout(); + + //author deletes group + olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + olatWorkflow1.getGroups().deleteGroup(GROUP_NAME_CHANGED); + olatWorkflow1.logout(); + } + + +} diff --git a/src/test/java/org/olat/test/functional/groups/CreateProjectGroupTest.java b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3f3f736b350e4498dbb465a65104d97b62518311 --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/CreateProjectGroupTest.java @@ -0,0 +1,38 @@ +package org.olat.test.functional.groups; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * User creates and deletes project group. + * <br/> + * Test setup: <br/> + * 1. Clean-up: missing? + * <p> + * Test case: <br/> + * 1. author creates group GROUP_NAME + * 2. author deletes group <br/> + * + * + * @author sandra + * + */ +public class CreateProjectGroupTest extends BaseSeleneseTestCase { + + public void testCreateProjectGroupTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OLATWorkflowHelper oLATWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + oLATWorkflowHelper.getGroups().createProjectGroup("project group selenium 1", ""); + Groups groups = oLATWorkflowHelper.getGroups(); + assertTrue(groups.isTextPresent("selenium 1")); + groups.deleteGroup("project group selenium 1"); + assertFalse(groups.isTextPresent("selenium 1")); + oLATWorkflowHelper.logout(); + assertEquals("OLAT - Online Learning And Training", oLATWorkflowHelper.getSelenium().getTitle()); + } +} diff --git a/src/test/java/org/olat/test/functional/groups/GroupConcurrenciesTest.java b/src/test/java/org/olat/test/functional/groups/GroupConcurrenciesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..994fd260c16bec5645d21364e5111936cf55c1fc --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/GroupConcurrenciesTest.java @@ -0,0 +1,86 @@ +package org.olat.test.functional.groups; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.group.Group; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.SeleniumException; + +/** + * + * Group owner and participant test project group concurrencies. + * <br/> + * Test setup: <br/> + * 1. Clean-up: delete all groups from author <br/> + * <p> + * Test case: <br/> + * 1. author creates group GROUP_NAME with group tool wiki <br/> + * 2. author adds participant <br/> + * 3. student logs in, check if he can select wiki <br/> + * 4. author removes wiki <br/> + * 5. student checks that wiki is no longer available and that he gets appropriate error message <br/> + * 6. author deletes group <br/> + * + * + * @author sandra + * + */ + +public class GroupConcurrenciesTest extends BaseSeleneseTestCase { + + public void testGroupConcurrencies() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // delete all my groups first !!! + WorkflowHelper.deleteAllGroupsFromAuthor(context.getStandardAuthorOlatLoginInfos(1)); + + // Author01 creates project group with wiki + System.out.println("logging in browser 1..."); + OLATWorkflowHelper oLATWorkflowHelper1 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + GroupAdmin groupAdmin1 = oLATWorkflowHelper1.getGroups().createProjectGroup("project group selenium 4", ""); + groupAdmin1.setTools(false, false, false, false, false, true, false); + String[] participants = {context.getStandardStudentOlatLoginInfos(1).getUsername()}; + groupAdmin1.addMembers(participants, new String[0]); + groupAdmin1.close("project group selenium 4"); + + // student01 opens group with wiki + System.out.println("logging in browser 2..."); + OLATWorkflowHelper oLATWorkflowHelper2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(2)); + Group group2 = oLATWorkflowHelper2.getGroups().selectGroup("project group selenium 4"); + group2.selectWiki(); + + // Author01 removes wiki + groupAdmin1 = oLATWorkflowHelper1.getGroups().selectGroup("project group selenium 4").selectAdministration(); + groupAdmin1.setTools(false, false, false, false, false, true, false); + + // Student01 wants to click on Wiki, but wiki was removed by the group owner + if(group2.hasWiki()) { + group2.selectWiki(); + } + Thread.sleep(10000); + //wiki dissapears silently/or not (why behaviour changes?) with a certain delay after removal + assertFalse(group2.hasWiki()); + + // Author01 deletes group + oLATWorkflowHelper1.getGroups().deleteGroup("project group selenium 4"); + + //student clicks on group and gets appropriate message + try{ + if (group2.getSelenium().isElementPresent("ui=group::menu_members()")) { + group2.selectMembers(); + } + } catch(SeleniumException e) { + // ok - ajax could come and refresh the group tab and notice that it has been modified right + // after we asked 'isElementPresent' .. hence not doing anything with this exception! + } + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (group2.isTextPresent("This group's configuration has been modified (group deleted, members changed). Please close the tab.")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + } +} diff --git a/src/test/java/org/olat/test/functional/groups/createprojectgroup.html b/src/test/java/org/olat/test/functional/groups/createprojectgroup.html new file mode 100644 index 0000000000000000000000000000000000000000..0c5d9577e433e53ad5de2ee13f167b412a0c1ec9 --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/createprojectgroup.html @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>groups_createprojectgroup</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">groups_createprojectgroup</td></tr> +</thead><tbody> +<!--Create project group and check if project group is listed in group tab--> +<tr> + <td>open</td> + <td>nightly</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::toolbox_create_projectGroup()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::createGroup_groupName()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupName()</td> + <td>project group selenium 1</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::createGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>selenium 1</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 1)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteYes()</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>selenium 1</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_add_users b/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_add_users new file mode 100644 index 0000000000000000000000000000000000000000..5803a770f7852f0d91a27fa1a8c6108f907a9caf --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_add_users @@ -0,0 +1,257 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>groups_createprojectgroup_add_users</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">groups_createprojectgroup_add_users</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>nightly</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::toolbox_create_projectGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupName()</td> + <td>project group selenium 3</td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupDescription()</td> + <td>selenium 3</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::createGroup_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_owners_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>author02</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=author02)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td></td> + <td>project group selenium 3</td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author02</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_configure_tools b/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_configure_tools new file mode 100644 index 0000000000000000000000000000000000000000..d574890f426e74c7b8f21ee8da904f1a8a7cb112 --- /dev/null +++ b/src/test/java/org/olat/test/functional/groups/groups_createprojectgroup_configure_tools @@ -0,0 +1,362 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>groups_createprojectgroup_configure_tools</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">groups_createprojectgroup_configure_tools</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>nightly</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::toolbox_create_projectGroup()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupName()</td> + <td>project group selenium 2</td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::createGroup_groupDescription()</td> + <td>second test</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::createGroup_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_description_groupDetails_groupName()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=group::content_description_groupDetails_groupName()</td> + <td>project group selenium 2 changed</td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_description_groupDetails_groupDescription()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=group::content_description_groupDetails_groupDescription()</td> + <td>description changed</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_description_groupDetails_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_tools_tabTools()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_information()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_contactForm()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_calendar()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_folder()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_forum()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_chat()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_collaborationTools_wiki()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_tools_collaborationTools_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_informationForMembers_formFieldInformationMembers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=group::content_tools_informationForMembers_formFieldInformationMembers()</td> + <td>hello everybody</td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_informationForMembers_save()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=group::content_tools_calendarAccess_calendarAccess()</td> + <td>label=Owners and tutors respectively</td> +</tr> +<tr> + <td>click</td> + <td>ui=group::content_tools_calendarAccess_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::content_members_tabMembers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_participants_addUsers()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=commons::searchUsers_userName()</td> + <td>student01</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::searchUsers_search()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=commons::usertable_adduser_checkUsername(nameOfUser=student01)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_choose()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::usertable_adduser_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>student01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=home::content_portlets_myGroups(nameOfGroup=project group selenium 2 changed)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_information()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>hello everybody</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_calendar()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Read only</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_members()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_email()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_folder()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_forum()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_chat()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=group::menu_wiki()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 2 changed)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveGroup(nameOfGroup=project group selenium 2 changed)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_leaveYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::groups()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteGroup(nameOfGroup=project group selenium 2 changed)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=groups::content_deleteYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::logOut()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/home/FolderTest.java b/src/test/java/org/olat/test/functional/home/FolderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d54cacb1703971894d2e5bbfcc426353a4c98476 --- /dev/null +++ b/src/test/java/org/olat/test/functional/home/FolderTest.java @@ -0,0 +1,147 @@ +package org.olat.test.functional.home; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.SinglePageEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Folder test class (See: OLAT-4394); tests the basic functionality of a folder. + * TODO: LD: see TODOs below. + * + * Test case: <br/> + * 1. go to personal folder/public <br/> + * 2. select all, delete selection <br/> + * 3. create file with name SAMPLE_FILE1 <br/> + * 4. rename file <br/> + * 5. edit file <br/> + * 6. assert that cannot create fie with invalid name <br/> + * 7. upload doc file <br/> + * 8. upload doc file again, do overwrite <br/> + * 9. create folder <br/> + * 10. assert that cannot create folder with invalid name <br/> + * 11. create zip file <br/> + * 12. assert that cannot create zip with invalid name <br/> + * 13. delete doc file, assert that really deleted. + * + * @author Lavinia Dumitrescu + * + */ +public class FolderTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseFolderTest"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + private final String SAMPLE_FILE1 = "selenium.txt"; + private final String SAMPLE_FILE2 = "selenium_mod.txt"; + private final String INVALID_FILE_NAME = "a:b"; + + private final String SAMPLE_FOLDER = "sample_folder"; + private final String INVALID_FOLDER_NAME_1 = "folder:1"; + + private final String ZIP_NAME = "archive"; + private final String INVALID_ZIP_NAME = "archive:zip"; + + public void setUp() throws Exception { + Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + } + + public void testPersonalFolder() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + + Folder folder = workflow.getHome().getPersonalFolder(); + folder.selectFileOrFolder("public"); + + //cleanup first + folder.selectAll(); + folder.deleteSelection(); + + //create file + boolean fileCreated = folder.createFile(null, SAMPLE_FILE1, "bla"); + assertTrue("Asserts file created.",fileCreated); + + //rename file + folder.editMetadata(SAMPLE_FILE1, SAMPLE_FILE2, "meta title", "meta description"); + assertTrue("Asserts file renamed.",folder.isFileOrFolderPresent(SAMPLE_FILE2)); + + //edit file + folder.editTxtFile(SAMPLE_FILE2, "any_text"); + assertEquals("Asserts text content.",folder.getText(SAMPLE_FILE2),"any_text"); + + //check that you cannot create file with an invalid name, empty, or already existing name + boolean notCreated = folder.createFile(null, INVALID_FILE_NAME, "bla"); + assertFalse("Asserts that cannot create file with invalid name", notCreated); + + //upload file + File doc = WorkflowHelper.locateFile(Context.FILE_RESOURCES_PATH + "Word.doc"); + String remoteDoc = Context.getContext().provideFileRemotely(doc); + folder.uploadFile(null, remoteDoc); + + //confirm overwrite file + boolean overwritten = folder.uploadWithOverwrite(null, remoteDoc, true); + assertTrue("Asserts that doc file was overwritten", overwritten); + + //TODO: check that you cannot upload file with an invalid name, cannot overwrite file without confirmation + + //create folder: selenium_folder + boolean folderCreated = folder.createFolder(SAMPLE_FOLDER); + assertTrue("Asserts folder created.", folderCreated); + + //check that one cannot create folder with an invalid name + folderCreated = folder.createFolder(INVALID_FOLDER_NAME_1); + assertFalse("Asserts that cannot create folder with invalid name.", folderCreated); + + //zip one or more files + List selection = new ArrayList(); + selection.add(doc.getName()); + boolean zipped = folder.zipSelection(selection, ZIP_NAME); + assertTrue("Asserts zip file created.", zipped); + assertTrue("Asserts that a zip with the given name is present.", folder.isFileOrFolderPresent(ZIP_NAME+".zip")); + + //check that you cannot use an invalid name for the zip file + zipped = folder.zipSelection(selection, INVALID_ZIP_NAME); + assertFalse("Asserts that cannot zip file with an invalid name.", zipped); + folder.cancelZipSelection(); + + //TODO: copy file to selenium_folder + //TODO:check that you cannot copy twice + //TODO:check that you cannot copy parent to child, but vice-versa should work + + //TODO:move file to folder, check that was moved + //TODO:check that you get notified if you move, copy, unzip file with an invalid name: see how to smuggle a data with an invalid name + + + //delete file + folder.deleteItem(doc.getName()); + assertFalse("Asserts that doc file was deleted.", folder.isTextPresent(doc.getName())); + } + + /** + * TODO: LD + */ + /*private void testStorageFolder() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + //create course + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + + //insert single page, create html page and assign to single page + SinglePageEditor singlePageEditor = (SinglePageEditor)courseEditor.insertCourseElement(CourseElemTypes.SINGLE_PAGE, true, "single page2"); + singlePageEditor.setDescription("This is the second course TS090533 Description"); + singlePageEditor.createHTMLPage("second_html_descr", "a not very long content that serves as an example too"); + + //delete html-page in the storage folder + Folder storageFolder = courseEditor.storageFolder(); + storageFolder.deleteItem("second_html_descr.html"); + }*/ + + +} diff --git a/src/test/java/org/olat/test/functional/home/HomeSettingsTest.java b/src/test/java/org/olat/test/functional/home/HomeSettingsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6d7333dcebe9c7ba18ce28eb25e288cd2b2b04b7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/home/HomeSettingsTest.java @@ -0,0 +1,78 @@ +package org.olat.test.functional.home; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.home.MySettings; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Tests change email for a user in Home Settings. + * <p> + * <br/> + * Test case: <br/> + * create user <br/> + * log in user <br/> + * open settings of user <br/> + * change email and show email on vcard <br/> + * assert activation e-mail for e-mail address confirmation was sent <br/> + * logout user <br/> + * admin deletes user <br/> + * + * + * @author alberto + */ +public class HomeSettingsTest extends BaseSeleneseTestCase { + + + private final String USER_NAME = "emailtestdummyuser" + System.currentTimeMillis(); + private final String USER_FNAME = "First"; + private final String USER_LNAME = "Last"; + private final String USER_EMAIL = System.currentTimeMillis() + "@user.com"; + private final String USER_PW = "olat3"; + + + public void testHome_settings() throws Exception { + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OLATWorkflowHelper olatWorkflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + + UserManagement userManagement = olatWorkflowAdmin.getUserManagement(); + + //create user + userManagement.createUser(USER_NAME, USER_FNAME, USER_LNAME, USER_EMAIL, USER_PW); + + // log in user + OLATWorkflowHelper olatWorkflowUserToDelete = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + + //open settings of user + MySettings mySettings = olatWorkflowUserToDelete.getHome().getUserSettings(); + + selenium = mySettings.getSelenium(); + + //change email and show email on vcard + mySettings.setEmail("NewEmailOfStudent01@olat-newinstall.com", true); + + //assert activation e-mail for e-mail address confirmation was sent + //TODO:LD: outcomment as soon as we have the email configured on olat instance: seleniumsinglevm & OLATNG (15.09.2010) + //assertTrue(selenium.isTextPresent("E-mail sent successfully")); + + //user logout + olatWorkflowUserToDelete.logout(); + + //admin deletes user + userManagement.deleteUserImmediately(USER_NAME); + olatWorkflowAdmin.logout(); //release possible locks + } + + + @Override + protected void cleanUpAfterRun() { + //login to release all possible locks + OLATWorkflowHelper olatWorkflowAdmin = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(1)); + } + + +} diff --git a/src/test/java/org/olat/test/functional/lr/CPTest.java b/src/test/java/org/olat/test/functional/lr/CPTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bae26b97451637f4b84e2384ae018414647b3781 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/CPTest.java @@ -0,0 +1,125 @@ +package org.olat.test.functional.lr; + +import java.io.File; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.CPResourceEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests the CP Editor. + * <br/> + * <p> + * Test setup:<br/> + * 1. clean-up: Delete CPs starting with CP_NAME_SUFFFIX. <br/> + * 2. author creates cp CP_NAME <br/> + * + * Test case: <br/> + * 1. login as author and go to tab learning resources <br/> + * 2. click "cp" in toolbox "create" <br/> + * 3. enter titel CPName <br/> + * 4. enter description CPDescription <br/> + * 5. click save <br/> + * 6. click next <br/> + * 7. open the editor? click yes <br/> + * 8. assure is visible "Lorem Ipsum" <br/> + * 9. rename page "Neue Seite" to "fi&rst paäge" <br/> + * 10. click "add page" <br/> <br/> + * 11. click edit "page properties" and rename added page to "renamed page" <br/> + * 12. copy "renamed page" <br/> + * 13. assure exists page "renamed page copy" <br/> + * 12. move "renamed page copy" to the same hierarchy as the "fi&rst paäge" <br/> ??? possible to drag&drop with selenium? + * 13. delete "renamed page copy" <br/> + * 14. click "delete menu element and files" <br/> + * 15. click "import page" <br/> + * 16. click select file <br/> + * 17. choose cptest.html and click open <br/> + * 18. click "Import" <br/> + * 19. assert that "cptest.html" is displayed (in the file navigation on the lefthand side) <br/> + * 20. click symbol "insert/edit image" <br/> + * 21. click "Browse" <br/> + * 22. click "Upload file" <br/> + * 23. click Select file and select OLATteam.jpg <br/> + * 24. click "Upload" <br/> + * 25. add Image description = OLAT Team, click "Insert" <br/> + * 26. click "save" <br/> + * 27. delete cp <br/> + * + * </p> + * + * @author Kristina Isacson / Lavinia Dumitrescu + * + */ + +public class CPTest extends BaseSeleneseTestCase { + + private final String CP_NAME = "CP"+System.currentTimeMillis(); + private final String CP_DESCRIPTION = "CPDescription"+System.currentTimeMillis(); + private final String CP_TEXT = "Lorem Ipsum"; + private final String CP_PAGE_DEFAULT_TITLE = "New page"; + private final String CP_PAGE_SPECIAL_TITLE = "fi&rst paäge"; + private final String CP_PAGE_TITLE1 = "renamed page"; + private final String CP_PAGE_CONTENT1 = "page content"; + private final String CP_PAGE_TITLE1_COPY = "renamed page copy"; //default title for o copy + private final String FILE_NAME1 = "cptest.html"; + private final String FILE_NAME2 = "OLATteam.jpg"; + private final String IMAGE_DESCRIPTION = "OLAT Team"; + + @Override + public void setUp() throws Exception { + super.setUp(); + + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // delete all LR from this author + WorkflowHelper.deleteAllLearningResourcesFromAuthor(context.getStandardAuthorOlatLoginInfos(1).getUsername()); + } + + + + public void testCP() throws Exception { + + OLATWorkflowHelper olatWorkflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + CPResourceEditor cPResourceEditor = olatWorkflow.getLearningResources().createCPAndStartEditing(CP_NAME, CP_DESCRIPTION); + + //select iframe + cPResourceEditor.getSelenium().selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + assertTrue("Asserts is text present: " + CP_TEXT, cPResourceEditor.isTextPresent(CP_TEXT)); + cPResourceEditor.getSelenium().selectFrame("relative=top"); + + cPResourceEditor.changeTitle(CP_PAGE_DEFAULT_TITLE, CP_PAGE_SPECIAL_TITLE); + cPResourceEditor.addPageAndRename(CP_PAGE_SPECIAL_TITLE, CP_PAGE_TITLE1, CP_PAGE_CONTENT1); + cPResourceEditor.copyPage(CP_PAGE_TITLE1); + assertTrue("Asserts a copy exists", cPResourceEditor.isTextPresent(CP_PAGE_TITLE1_COPY)); + + //move CP_PAGE_TITLE1_COPY as root child + //cPResourceEditor.movePage(CP_PAGE_TITLE1, CP_PAGE_TITLE1_COPY); + + cPResourceEditor.deletePage(CP_PAGE_TITLE1_COPY, false); + + File file = WorkflowHelper.locateFile(FILE_NAME1); + String remoteHtml = Context.getContext().provideFileRemotely(file); + cPResourceEditor.importPage(CP_PAGE_SPECIAL_TITLE, remoteHtml); + assertTrue("Asserts that file was imported", cPResourceEditor.isTextPresent(FILE_NAME1)); + + //insert image + file = WorkflowHelper.locateFile(FILE_NAME2); + remoteHtml = Context.getContext().provideFileRemotely(file); + cPResourceEditor.insertImage(remoteHtml, IMAGE_DESCRIPTION); + System.out.println("image inserted"); + + } + + + + @Override + protected void cleanUpAfterRun() { + WorkflowHelper.deleteLearningResources(Context.getContext().getStandardAuthorOlatLoginInfos(1).getUsername(), CP_NAME); + } + + +} diff --git a/src/test/java/org/olat/test/functional/lr/ClusterWikiTest.java b/src/test/java/org/olat/test/functional/lr/ClusterWikiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..74c592be6c86456611678175497a2cf7b0bc82ec --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/ClusterWikiTest.java @@ -0,0 +1,127 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * test wiki functionality (editing wikipages, check GUI lock, select all menu options like Index A to Z etc. show VErsion and Compare) within a cluster <br/> + * <p> + * Test setup: <br/> + * 1. Login as Admin in browser 1 <br/> + * 2. Login as Author in browser 2 <br/> + * 3. cleanup at the end <br/> + * + * Test case: <br/> + * 1. Admin logs in in browser 1 <br/> + * 2. Author logs in in browser 2 <br/> + * 3. Admin creates a wiki and changes access to all registered users <br/> + * 4. Wiki is schown, Admin inserts link test in wiki and clicks it <br/> + * 5. Admin enters word "testing" in wiki page and it is checked whether "testing" is present <br/> + * 6. Author displays the wiki (on a different node), checks whether "test"-page is there <br/> + * 7. Author searches for "test" and checks that "testing" is displayed <br/> + * 8. Admin edits wiki <br/> + * 9. check that Author gets the message "is currently modified by" <br/> + * 10. show article "testing" in both browsers <br/> + * 11. Admin adds "lorem ibsum" <br/> + * 12. check that Author sees "lorem ibsum" <br/> + * 13. Admin clicks create or search "test", check if page is displayed <br/> + * 14. Admin clicks links in the navigation box <br/> + * 15. cleanup <br/> + * + * </p> + * + * @author guido + * + */ +public class ClusterWikiTest extends BaseSeleneseTestCase { + + private OLATWorkflowHelper workflow1; + private OLATWorkflowHelper workflow2; + + + public void testMultiBrowserClusterWiki() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + String wikiName = "wikijunit-"+System.currentTimeMillis(); + + // login first + System.out.println("logging in browser 1..."); + workflow1 = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + + System.out.println("logging in browser 2..."); + workflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(2)); + + //browser 1 + //create a wiki and change access for all users + LRDetailedView lRDetailedView = workflow1.getLearningResources().createResource(wikiName, "test", LR_Types.WIKI); + lRDetailedView.modifyProperties(LRDetailedView.ACCESS_ALL_REGISTERED); + WikiRun wikiRun1 = lRDetailedView.showWikiContent(); + wikiRun1.editPage("[[test]]"); + wikiRun1.getSelenium().click("ui=wiki::article_testLink()"); + //wikiRun1.getSelenium().waitForPageToLoad("30000"); + wikiRun1.editPage("testing"); + assertTrue(wikiRun1.isTextPresent("testing")); + + //browser 2 + //start the wiki with the second user on the second node and check content + WikiRun wikiRun2 = workflow2.getLearningResources().showWikiContent(wikiName); + assertTrue(wikiRun2.isTextPresent("test")); //true: successfully loaded the page in the second node + //wikiRun2.searchArticle("test"); + wikiRun2.createOrSearchArticle("test", null); + assertTrue(wikiRun2.isTextPresent("testing")); //true: successfully loaded the page in the second node + + //browser 1 + wikiRun1.openEditor();//try to edit page. Second user should have GUI lock on this page + Thread.sleep(2000); + + //browser 2 + wikiRun2.openEditor(); + assertTrue(wikiRun2.isTextPresent("is being modified by")); //WARNING: HERE POTENTIAL FAILURE EACH TIME THE TRANSLATION CHANGES! + + //continue both + + //browser 1 + wikiRun1.showArticle(); + assertTrue(wikiRun1.isTextPresent("testing")); + + //browser 2 + wikiRun2.showArticle(); + assertTrue(wikiRun2.isTextPresent("testing")); + + //browser 1 + //edit page: second user on node 2 should see new content + wikiRun1.editPage("lorem ibsum"); + + + //browser 2 + wikiRun2.createOrSearchArticle("test", null); + assertTrue(wikiRun2.isTextPresent("lorem ibsum"));//true: new content visible on node 2 + + + //browser 1 + //continue with basic tests + wikiRun1.createOrSearchArticle("test", null); + assertTrue(wikiRun1.isTextPresent("lorem ibsum")); + wikiRun1.selectIndex(); + wikiRun1.selectFromAToZ(); + wikiRun1.editMenu("* [[Index]]\n* [[Index|Your link]]\n* [[test]]"); + wikiRun1.selectIndex(); + wikiRun1.createOrSearchArticle("test", null); + wikiRun1.showVersionsAndCompare(); + assertTrue(wikiRun1.isTextPresent("+ testing")); + + + } + + @Override + public void cleanUpAfterRun() { + workflow1.logout(); + workflow2.logout(); + } + + +} diff --git a/src/test/java/org/olat/test/functional/lr/CreateLearningRessourcesTest.java b/src/test/java/org/olat/test/functional/lr/CreateLearningRessourcesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..556dacfd22c48bb69a35dea9a01103522634e324 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/CreateLearningRessourcesTest.java @@ -0,0 +1,132 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.CPResourceEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.ResourceEditor; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates learning resources, learning resources are deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates all learning resources <br/> + * 2. Cleanup in the beginning and end: All learning resources are deleted <br/> + * + * Test case: <br/> + * 1. Author creates learning resource (course, glossary, questionnaire, resource folder, test, wiki, cp, blog, podcast, todo: eportfolio template)<br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. Learning resources course, questionnaire and test are copied + * 5. Learning resources are deleted <br/> + * </p> + * + * @author kristina + */ + +public class CreateLearningRessourcesTest extends BaseSeleneseTestCase { + private final String GLOSSARY_NAME = "GlossaryName" + System.currentTimeMillis();; + private final String CP_NAME = "CP"+System.currentTimeMillis(); + private final String CP_DESCRIPTION = "CPDescription"+System.currentTimeMillis(); + private final String BLOG_TITLE = "My blog title"; + private final String PODCAST_TITLE = "My podcast title"; + private final String DESC = "My first lr"; + private final String COPY_TITLE = "Copy"; + private final String COPY_DESCRIPTION = "Copy Description"; + + //create course + public void testCreateCourseTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + LearningResources learningResources = olatWorkflow.getLearningResources(); + CourseEditor courseEditor = learningResources.createCourseAndStartEditing("CourseName", "CourseDescription"); + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + //copy course + lRDetailedView.copyLR(COPY_TITLE, COPY_DESCRIPTION); + + } + + + + //create glossary + public void testCreateGlossaryTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + LearningResources learningResources = olatWorkflow.getLearningResources(); + learningResources.createGlossaryAndStartEditing(GLOSSARY_NAME, "GlossaryDescription"); + + //cleanup + learningResources = olatWorkflow.getLearningResources(); + learningResources.searchMyResource(GLOSSARY_NAME); + + } + + //create questionnaire + public void testCreateQuestionnaireTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflowHelper.getLearningResources().createQuestionnaireAndStartEditing("QuestionnaireName", "QuestionnaireDescription"); + LRDetailedView lRDetailedView = testEditor.close(); + //copy questionnaire + lRDetailedView.copyLR(COPY_TITLE, COPY_DESCRIPTION); + } + + //create resource folder + public void testCreateResourcefolderTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + ResourceEditor resourceEditor = olatWorkflow.getLearningResources().createResourceFolderAndStartEditing("ResourcefolderName", "ResourcefolderDescription"); + resourceEditor.close(); + + } + + //create test + public void testCreateTestTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflowHelper.getLearningResources().createTestAndStartEditing("TestName", "TestDescription"); + LRDetailedView lRDetailedView = testEditor.close(); + //copy test + lRDetailedView.copyLR(COPY_TITLE, COPY_DESCRIPTION); + } + + //create wiki + public void testCreateWikiTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + olatWorkflow.getLearningResources().createResource("WikiName", "WikiDescription", LR_Types.WIKI); + + } + + //create cp content + public void testCP() throws Exception { + + OLATWorkflowHelper olatWorkflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos(1)); + olatWorkflow.getLearningResources().createCPAndStartEditing(CP_NAME, CP_DESCRIPTION); + } + + //create blog and podcast + public void testCreateLRBlogPodcast() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + // create blog + LearningResources lr1 = olatWorkflow.getLearningResources(); + lr1.createResource(BLOG_TITLE, DESC, LearningResources.LR_Types.BLOG); + + //create podcast + lr1.createResource(PODCAST_TITLE, DESC, LearningResources.LR_Types.PODCAST); + } + +} diff --git a/src/test/java/org/olat/test/functional/lr/DeleteAllCoursesTest.java b/src/test/java/org/olat/test/functional/lr/DeleteAllCoursesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..75e111fea63ca96df296fd0c0e7fd02e317d0be6 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/DeleteAllCoursesTest.java @@ -0,0 +1,36 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * StandardAdmin creates and deletes courses<br/> + * <br/> + * Testsetup: <br/> + * 1. Admin creates 10 courses<br/> + * Testcase: <br/> + * 1. Admin creates 10 courses with prefix deletetest <br/> + * 2. Admin deletes all courses with prefix deletetest <br/> + * + * @author eglis + * + */ +public class DeleteAllCoursesTest extends BaseSeleneseTestCase { + + public void testDeleteAllCourses() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + + String myRandomName="deletetest-"+System.currentTimeMillis(); + + for(int i=0; i<10; i++) { + workflow.getLearningResources().createResource(myRandomName, myRandomName, LR_Types.COURSE); + } + + WorkflowHelper.deleteAllCoursesNamed(myRandomName); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/TestBlogAndPodcastLinks.java b/src/test/java/org/olat/test/functional/lr/TestBlogAndPodcastLinks.java new file mode 100644 index 0000000000000000000000000000000000000000..83784813242948dace1e84910320255564686c67 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/TestBlogAndPodcastLinks.java @@ -0,0 +1,79 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.BlogEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.BlogResource; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * + * test new xpaths + * <br/> + * <p> + * Test setup: <br/> + * create lr blog and podcast from tab lr and delete afterward<br/> + * insert blog and podcast bb<br/> + * <p> + * Test case: <br/> + * edit internal blog <br/> + * edit blog in new tab <br/> + * blogResource.createEntry(title, description, content) <br/> + * publish and preview <br/> + * + * + * + * + * @author sandra, finishing: alberto + */ +public class TestBlogAndPodcastLinks extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String BLOG_TITLE = "My blog title"; + private final String PODCAST_TITLE = "My podcast title"; + private final String DESC = "My first lr"; + private final String BLOG_URI = ""; + private final String BLOG_DESC = "BLOG_DESC"; + + + + public void testCreateLRBlogPodcast() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + // create lr blog and podcast from tab lr and delete afterward --> ok + LearningResources lr1 = olatWorkflow.getLearningResources(); + LRDetailedView lrdv = lr1.createResource(BLOG_TITLE, DESC, LearningResources.LR_Types.BLOG); + LearningResources lr2 = lrdv.deleteLR(); + LRDetailedView lrdv2 = lr2.createResource(PODCAST_TITLE, DESC, LearningResources.LR_Types.PODCAST); + LearningResources lr3 = lrdv2.deleteLR(); + + // insert blog and podcast bb --> ok + CourseEditor courseEditor = lr3.createCourseAndStartEditing(COURSE_NAME, DESC); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.BLOG, true, BLOG_TITLE); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.PODCAST, true, PODCAST_TITLE); + + + // edit internal blog + BlogEditor blogEditorInt = (BlogEditor)courseEditor.selectCourseElement(BLOG_TITLE); + blogEditorInt.create(BLOG_TITLE, BLOG_DESC); + + // edit blog in new tab + BlogResource blogResource = blogEditorInt.edit(); + + //blogResource.createEntry(title, description, content) + blogResource.createEntry("HongKong", "HongKong entry description", "dubai entry content", true); + + // publish and preview + LRDetailedView lRDetailedView = blogResource.close(); + courseEditor = lRDetailedView.editCourseContent(); + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_RemoveOwnerTest.java b/src/test/java/org/olat/test/functional/lr/lr_RemoveOwnerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a974588860ff0532163242629aae6944fca3663c --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_RemoveOwnerTest.java @@ -0,0 +1,75 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Test checks, if it is ensured that each learning resource has at least one owner. Course is deleted at the end<br/> + * <p> + * <br/> + * Test setup: <br/> + * 1. Authors logs in in Browser 1 and creates course and adds Student as owner <br/> + * 2. Student logs in in Browser 2 <br/> + * <br/> + * Test case: <br/> + * 1. user1 creates course COURSE_NAME with two owners (user1 and user2)<br/> + * 2. user2 enters the course <br/> + * 3. user1 removes user2 as owner <br/> + * 4. user1 tries to remove himself as owner <br/> + * 5. check, if the message "At least one user is required in a group" appears <br/> + * 6. delete the course COURSE_NAME <br/> + * </p> + * + * @author kristina + */ + +public class lr_RemoveOwnerTest extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseName" + System.currentTimeMillis(); + + + public void testlr_RemoveOwnerTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OlatLoginInfos user1 = context.getStandardAuthorOlatLoginInfos(); + OlatLoginInfos user2 = context.getStandardStudentOlatLoginInfos(); + + System.out.println("logging in browser 1..."); + OLATWorkflowHelper olatWorkflowHelper1 = context.getOLATWorkflowHelper(user1); + + LRDetailedView lRDetailedView1 = null; + try { + // user1 creates course CourseName with two owners + CourseEditor courseEditor1 = olatWorkflowHelper1.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "CourseDescription"); + lRDetailedView1 = courseEditor1.closeToLRDetailedView(); + //assign only one new owner + lRDetailedView1.assignOwner(user2.getUsername()); + + // user2 opens detail view of COURSE_NAME with browser 2 + System.out.println("logging in browser 2..."); + OLATWorkflowHelper olatWorkflowHelper2 = context.getOLATWorkflowHelper(user2); + LRDetailedView lRDetailedView2 = olatWorkflowHelper2.getLearningResources().searchMyResource(COURSE_NAME); + + // now remove user2 in browser 1 + lRDetailedView1.removeOwner(user2.getUsername()); + + // now user1 tries to remove himself in browser 1 + Boolean successfullyRemoved = lRDetailedView1.removeOwner(user1.getUsername()); + assertNotNull(successfullyRemoved); + assertFalse(successfullyRemoved); + } finally { + if(lRDetailedView1!=null) { + lRDetailedView1.deleteLR(); + } + } + + // excellent, close course in browser 2 + // selenium2.click("ui=tabs::closeCourse(nameOfCourse=CourseName)"); + + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_concurrenciesDelete.java b/src/test/java/org/olat/test/functional/lr/lr_concurrenciesDelete.java new file mode 100644 index 0000000000000000000000000000000000000000..24b711a3e3d7461faaa9f79f50b0d60a2048c227 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_concurrenciesDelete.java @@ -0,0 +1,77 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Check if Student receives the message, that the Author has deleted the course. <br/> + * <p> + * Test setup: <br/> + * 1. Author creates course <br/> + * 2. Author deletes course which Student is viewing <br/> + * Test case: <br/> + * 1. Author creates course with forum, publishes course and sets access to all registered OLAT users. <br/> + * 2. Student opens course in course-run in browser 2 <br/> + * 3. Author deletes the course in browser 1 <br/> + * 4. Student clicks the link forum <br/> + * 5. Check if Student receives the message, that the course was deleted. <br/> + * + * </p> + * + * @author kristina + */ + +public class lr_concurrenciesDelete extends BaseSeleneseTestCase { + + private final String COURSE_NAME = "CourseName"; + + + + public void testlr_concurrenciesDelete() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OlatLoginInfos user1 = context.getStandardAuthorOlatLoginInfos(); + OlatLoginInfos user2 = context.getStandardStudentOlatLoginInfos(); + + // Author creates course CourseName with forum and open the detail view of course 'CourseName' + System.out.println("logging in browser 1..."); + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(user1); + LearningResources learningResources1 = olatWorkflow1.getLearningResources(); + CourseEditor courseEditor = learningResources1.createCourseAndStartEditing(COURSE_NAME, "CourseDescription"); + courseEditor.insertCourseElement(CourseElemTypes.FORUM, true, null); + courseEditor.publishCourse(); + courseEditor.closeToLRDetailedView(); + LRDetailedView lRDetailedView1 = learningResources1.searchResource(COURSE_NAME, null); + + // Student opens 'CourseName' with browser 2 + System.out.println("logging in browser 2..."); + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(user2); + LearningResources learningResources2 = olatWorkflow2.getLearningResources(); + LRDetailedView lRDetailedView2 = learningResources2.searchResource(COURSE_NAME, null); + CourseRun courseRun2 = lRDetailedView2.showCourseContent(); + + // Author deletes 'CourseName' in browser 1 + lRDetailedView1.deleteLR(); + + // after that Student clicks 'Forum' in browser 2 + // beware of polling which already shows the message "this course..." + // to stabilize the test: check first if Forum is available. + // test may still fail because of polling before clicking, but the probability is lowered. + if(courseRun2.isElementPresent("Forum")){ + courseRun2.selectCourseElement("Forum"); + } + //and waits until 'This course has been modified.' appears + SeleniumHelper.waitUntilTextPresent(courseRun2.getSelenium(), "This course has been modified.", 20); + // excellent, close course in browser 2 + courseRun2.close(COURSE_NAME); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createCourseAMTest.java b/src/test/java/org/olat/test/functional/lr/lr_createCourseAMTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8ce3e098d75c528b2e1c45bf98ccd3ee6f800719 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createCourseAMTest.java @@ -0,0 +1,49 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates course, insert title and description, add owner, change access, delete course <br/> + * <p> + * Test setup: <br/> + * 1. Author creates course <br/> + * 2. course is deleted at the end<br/> + * Test case: <br/> + * 1. Author creates course CourseName <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. Author clicks assign owners, adds owner <br/> + * 5. Author clicks modify properties <br/> + * 6. Author changes to all registered OlAT users, save <br/> + * 7. course is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createCourseAMTest extends BaseSeleneseTestCase { + + + + public void testlr_createCourseAMTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + String standardPassword = context.getStandardStudentOlatLoginInfos().getPassword(); + OlatLoginInfos secondUser = context.createuserIfNotExists(1, "coursenameauthor", standardPassword, true, true, true, true, false); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing("CourseName", "CourseDescription"); + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + lRDetailedView.assignOwner(secondUser.getUsername()); + lRDetailedView.modifyProperties("All registered OLAT users"); + + //delete course + lRDetailedView.deleteLR(); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createCourseTest.java b/src/test/java/org/olat/test/functional/lr/lr_createCourseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3d4d7ad5a819340cf1d039563eb48090e3ae1336 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createCourseTest.java @@ -0,0 +1,42 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates course, starts editor, closes editor, course is deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates course <br/> + * 2. course is deleted <br/> + * + * Test case: <br/> + * 1. Author creates course <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. course is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createCourseTest extends BaseSeleneseTestCase { + + + + public void testlr_createCourseTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + LearningResources learningResources = olatWorkflow.getLearningResources(); + CourseEditor courseEditor = learningResources.createCourseAndStartEditing("CourseName", "CourseDescription"); + LRDetailedView lRDetailedView = courseEditor.closeToLRDetailedView(); + //cleanup + lRDetailedView.deleteLR(); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createGlossaryTest.java b/src/test/java/org/olat/test/functional/lr/lr_createGlossaryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d05f36f3ce1fc940eddf45bcb60e20470cabd61b --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createGlossaryTest.java @@ -0,0 +1,46 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates glossary, starts editor, closes editor, glossary is deleted <br/> + * <p> + * Test setup: <br/> + * 1. cleanup <br/> + * 2. Author creates glossary <br/> + * 3. glossary is deleted <br/> + * + * Test case: <br/> + * 1. Author creates glossary <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. glossary is deleted<br/> + * </p> + * + * @author kristina + */ +public class lr_createGlossaryTest extends BaseSeleneseTestCase { + + private final String GLOSSARY_NAME = "GlossaryName" + System.currentTimeMillis();; + + + public void testlr_createGlossaryTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + + LearningResources learningResources = olatWorkflow.getLearningResources(); + learningResources.createGlossaryAndStartEditing(GLOSSARY_NAME, "GlossaryDescription"); + + //cleanup + learningResources = olatWorkflow.getLearningResources(); + LRDetailedView lRDetailedView = learningResources.searchMyResource(GLOSSARY_NAME); + lRDetailedView.deleteLR(); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createQuestionnaireTest.java b/src/test/java/org/olat/test/functional/lr/lr_createQuestionnaireTest.java new file mode 100644 index 0000000000000000000000000000000000000000..534867ae7112dcbd0fc7a06e6986a8a38216e6fc --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createQuestionnaireTest.java @@ -0,0 +1,40 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates questionnaire, starts editor, closes editor, questionnaire is deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates questionnaire <br/> + * 2. questionnaire is deleted <br/> + * + * Test case: <br/> + * 1. Author creates questionnaire <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. questionnaire is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createQuestionnaireTest extends BaseSeleneseTestCase { + + + + public void testlr_createQuestionnaireTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflowHelper.getLearningResources().createQuestionnaireAndStartEditing("QuestionnaireName", "QuestionnaireDescription"); + LRDetailedView lRDetailedView = testEditor.close(); + + //questionnaire is deleted + lRDetailedView.deleteLR(); + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createResourcefolderTest.java b/src/test/java/org/olat/test/functional/lr/lr_createResourcefolderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..317ec047f2961387db191dffc482e623737002c7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createResourcefolderTest.java @@ -0,0 +1,42 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.ResourceEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates resource folder, starts editor, closes editor, resource folder is deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates resource folder <br/> + * + * + * Test case: <br/> + * 1. Author creates resource folder <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. resource folder is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createResourcefolderTest extends BaseSeleneseTestCase { + + + + public void testlr_createResourcefolderTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + ResourceEditor resourceEditor = olatWorkflow.getLearningResources().createResourceFolderAndStartEditing("ResourcefolderName", "ResourcefolderDescription"); + LRDetailedView lRDetailedView = resourceEditor.close(); + + // resource folder is deleted + lRDetailedView.deleteLR(); + + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createTestTest.java b/src/test/java/org/olat/test/functional/lr/lr_createTestTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c75a1e214ea5594b0bb863f357bdec39aa5a09e7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createTestTest.java @@ -0,0 +1,40 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Author creates test, starts editor, closes editor, tes is deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates test <br/> + * <br/> + * Test case: <br/> + * 1. Author creates test <br/> + * 2. Author starts editor <br/> + * 3. Author closes editor <br/> + * 4. test is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createTestTest extends BaseSeleneseTestCase { + + + + public void testlr_createTestTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflowHelper.getLearningResources().createTestAndStartEditing("TestName", "TestDescription"); + LRDetailedView lRDetailedView = testEditor.close(); + + // test is deleted + lRDetailedView.deleteLR(); + + } +} diff --git a/src/test/java/org/olat/test/functional/lr/lr_createWikiTest.java b/src/test/java/org/olat/test/functional/lr/lr_createWikiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a68a691b64e40e9fc8887c0eec2fe4f7ffe4a50b --- /dev/null +++ b/src/test/java/org/olat/test/functional/lr/lr_createWikiTest.java @@ -0,0 +1,38 @@ +package org.olat.test.functional.lr; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; + +/** + * Author creates wiki, wiki is deleted <br/> + * <p> + * Test setup: <br/> + * 1. Author creates wiki <br/> + * <br/> + * Test case: <br/> + * 1. Author creates wiki <br/> + * 2. wiki is deleted <br/> + * </p> + * + * @author kristina + */ + +public class lr_createWikiTest extends BaseSeleneseTestCase { + + + + public void testlr_createWikiTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + LRDetailedView lRDetailedView = olatWorkflow.getLearningResources().createResource("WikiName", "WikiDescription", LR_Types.WIKI); + + // wiki is deleted + lRDetailedView.deleteLR(); + + } +} diff --git a/src/test/java/org/olat/test/functional/portfolio/CollectOrCreateArtefactTest.java b/src/test/java/org/olat/test/functional/portfolio/CollectOrCreateArtefactTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fe1d297bd015730e0942db3d6a652cb0325f6b17 --- /dev/null +++ b/src/test/java/org/olat/test/functional/portfolio/CollectOrCreateArtefactTest.java @@ -0,0 +1,127 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.functional.portfolio; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.StructureElement; +import org.olat.test.util.selenium.olatapi.portfolio.EPArtefactSearch; +import org.olat.test.util.selenium.olatapi.portfolio.EPCollectWizard; +import org.olat.test.util.selenium.olatapi.portfolio.EPExtensions; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/** + * ePortfolio: testing + * - artefact collection + * - artefact creation + * - filtering with search + * - deleting artefacts + * + * + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + */ +public class CollectOrCreateArtefactTest extends BaseSeleneseTestCase { + + private static final String FORUM_SUBJECT = "forum artefact test"; + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + } + + /** + * - creates a forum post in the demo course + * - collect it as an artefact using the wizard + * - check that the artefact exists + * @throws Exception + */ + @Test + public void testCollectForumPost() throws Exception { + //cleanup first + cleanUpArtefacts(); + + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_1); + courseRun.selectAnyButGetToRoot("Activation Interaction"); + Forum forum = courseRun.selectForum("Forum"); + forum.openNewTopic(FORUM_SUBJECT, "Forum Message to collect as artefact"); + courseRun.selectForum("Forum").viewTopic(FORUM_SUBJECT); + + EPCollectWizard epwizz = forum.collectAsArtefact(); + assertNotNull("forum post seems not to be collectable or ePortfolio is turned off", epwizz); + epwizz.filloutWizardForOLATSource(FORUM_SUBJECT, "a test to collect a forum artefact"); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + assertEquals(1, epExt.getTotalArtefactAmount()); + workflow.logout(); + } + + private void cleanUpArtefacts() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + //cleanup first + EPExtensions epExt = workflow.getHome().getEPortfolio(); + while(epExt.hasArtefact()) { + epExt.deleteFirstArtefact(); + Thread.sleep(3000); + } + } + + /** + * - create a new text-artefact + * - search for it by artefact-type + * not functional in web 1.0 mode + */ + @Test(dependsOnMethods ={"testCollectForumPost"}) + public void testCreateTextArtefact() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPCollectWizard epWizz = epExt.createTextArtefactAndOpenWizard(); + epWizz.filloutWizardForTextArtefact("a great content for an artefact...", "text artefact", "how great it is"); + // filter for textartefact and get amount + EPArtefactSearch epSearch = epExt.getArtefactSearch(); + epSearch.toggleTextArtefactFilter(); + assertEquals(1, epExt.getArtefactAmount()); + workflow.logout(); + } + + /** + * - deletes 2 artefacts (created before) + * - check that no more artefacts exist + */ + @Test(dependsOnMethods ={"testCreateTextArtefact"}) + public void testDeleteArtefacts(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + EPExtensions epExt = workflow.getHome().getEPortfolio(); + assertEquals(2, epExt.getTotalArtefactAmount()); + epExt.deleteFirstArtefact(); + epExt.deleteFirstArtefact(); + assertEquals(0, epExt.getTotalArtefactAmount()); + workflow.logout(); + } + +} diff --git a/src/test/java/org/olat/test/functional/portfolio/CreateFillAndShareMapTest.java b/src/test/java/org/olat/test/functional/portfolio/CreateFillAndShareMapTest.java new file mode 100644 index 0000000000000000000000000000000000000000..33bbfdfb46335053ce8b0c22b29d9824c9bad40b --- /dev/null +++ b/src/test/java/org/olat/test/functional/portfolio/CreateFillAndShareMapTest.java @@ -0,0 +1,134 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.functional.portfolio; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.portfolio.EPCollectWizard; +import org.olat.test.util.selenium.olatapi.portfolio.EPExtensions; +import org.olat.test.util.selenium.olatapi.portfolio.EPMapEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * ePortfolio: this is testing the following scenarios: + * - creates a map + * - add pages and structures to this map + * - link artefacts in map + * - share map to others + * - edit a map + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + * + */ +public class CreateFillAndShareMapTest extends BaseSeleneseTestCase { + + private static final String SELENIUM_TEST_MAP_TITLE = "selenium test map"; + + public void setUp() throws Exception { + Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + } + @Test + public void testCreateDefaultMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.createDefaultMap(SELENIUM_TEST_MAP_TITLE, "its cold outside, fill this map with funny stuff ;)"); + epMap.toggleEditMode(false); + } + + @Test(dependsOnMethods ={"testCreateDefaultMap"}) + public void testAddPagesToMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.openMapByTitle(SELENIUM_TEST_MAP_TITLE); + epMap.addPages(2); + } + @Test(dependsOnMethods ={"testAddPagesToMap"}) + public void testAddStructuresToMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.openMapByTitle(SELENIUM_TEST_MAP_TITLE); + epMap.openFirstPage(); + epMap.addStructures(3); + } + @Test(dependsOnMethods ={"testAddStructuresToMap"}) + public void testFillMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + // create an artefact to be sure one exists + EPCollectWizard epWizz = epExt.createTextArtefactAndOpenWizard(); + epWizz.filloutWizardForTextArtefact("a great content for an artefact...", "text artefact", "how great it is"); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.openMapByTitle(SELENIUM_TEST_MAP_TITLE); + epMap.openFirstPage(); + // attach to first page + selenium.click("ui=epMap::attachArtefactToPageLink()"); + selenium.waitForPageToLoad("30000"); + // set view to details mode! + selenium.click("ui=epArtefactSearch::viewModeDetails()"); + selenium.click("ui=epArtefactSearch::firstArtefactChooseLink()"); + selenium.waitForPageToLoad("30000"); + // attach to a structure + selenium.click("ui=epMap::attachArtefactToStructLink()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=epArtefactSearch::firstArtefactChooseLink()"); + selenium.waitForPageToLoad("30000"); + } + @Test(dependsOnMethods ={"testFillMap"}) + public void testShareMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.openShareDialogForMapByTitle(SELENIUM_TEST_MAP_TITLE); + epMap.shareToOtherUserWithName("administrator"); + } + @Test(dependsOnMethods ={"testShareMap"}) + public void testEditMap(){ + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + selenium = workflow.getSelenium(); + EPExtensions epExt = workflow.getHome().getEPortfolio(); + EPMapEditor epMap = epExt.getMapEditor(); + epMap.openMapByTitle(SELENIUM_TEST_MAP_TITLE); + epMap.openFirstPage(); + epMap.toggleEditMode(true); + // first page was selected before, edit title&desc + epMap.changeElementTitleDescription("a new title for this page", "and even a better description! how great is this!"); + // delete all pages + while (!workflow.isTextPresent("at least one page")){ + if (!epMap.deleteActiveTOCElement()) break; + // workaround to get to a page again + epMap.toggleEditMode(false); + epMap.openFirstPage(); + epMap.toggleEditMode(true); + } + assertTrue(workflow.isTextPresent("at least one page")); + epMap.toggleEditMode(false); + } + +} diff --git a/src/test/java/org/olat/test/functional/search/MultiUserSearchTest.java b/src/test/java/org/olat/test/functional/search/MultiUserSearchTest.java new file mode 100644 index 0000000000000000000000000000000000000000..95fe84d970987746eac9fb36b8a8bb60282fff3f --- /dev/null +++ b/src/test/java/org/olat/test/functional/search/MultiUserSearchTest.java @@ -0,0 +1,257 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.functional.search; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * Search service test with several users and several search queries. <p> + * + * THIS TEST ONLY RUNS AGAINST AN OLAT WITH SEARCH ACTIVATED. <br/> + * + * Test setup: <br/> + * It needs a property file (see searchTest.properties) with the following data: <br/> + * - user names - it is assumed that the users are already defined in OLAT <br/> + * - search query pool <br/> + * - max. number of searches before logout: maxSearches <br/> + * - testSpanMs - max running time of the test <br/> + * - timeToWaitBetweenSearches <br/> + * + * @author Lavinia Dumitrescu + * + */ +public class MultiUserSearchTest extends BaseSeleneseTestCase { + + private final String PROPERTIES_FILE_NAME = "org/olat/test/functional/search/searchTest.properties"; + + private List<String> userNamesList = new ArrayList<String>(); + + private List<String> searchQueryList = new ArrayList<String>(); + private Iterator<String> queryIterator; + + private final String SERVICE_NOT_AVAILABLE_MSG = "This service is temporarily unavailable."; + private final String RESULTS_FOUND = "Results 1"; + private final String NO_RESULTS_FOUND = "No results found."; + + private String timeToWaitBetweenSearches = "30000"; + private int maxSearches = 5; //max. number of searches before logout + private long testSpanMs; + private long startTimeStampMs; + + + + public void setUp() throws Exception { + //no need to setup the context + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + getTestData(); + startTimeStampMs = System.currentTimeMillis(); + } + + /** + * Search in loop for the testSpanMs. + * @throws Exception + */ + public void testSearch() throws Exception { + while(System.currentTimeMillis()-startTimeStampMs<testSpanMs) { + searchForOneLogin(); + } + } + + /** + * Tests the search instance with a configurable: + * - number of users + * - search query pool + * - number of searches per user - between login and logout + * - timeToWaitBetweenSearches + * + * @throws Exception + */ + public void searchForOneLogin() throws Exception { + System.out.println("testSearch STARTED"); + + List<Selenium> seleniumList = new ArrayList<Selenium>(); + //create a selenium instance for each user, and let the users sent the first search request + for(String username : userNamesList) { + String standardPassword = Context.getContext().getStandardAdminOlatLoginInfos(1).getPassword(); + //TODO:LD: create user with different roles + Context.getContext().createuserIfNotExists(1, username, standardPassword, true, false, false, false, false); + //we assume that all tests users have the same login, and the user already exists in the target olat instance (default users) + Selenium selenium_ = createSeleniumAndLogin(username, standardPassword); + seleniumList.add(selenium_); + + //search after login + String luceneQuery = getNextSearchQuery(); + selenium_.type("ui=search::topnavSearchInput()", luceneQuery); + selenium_.click("ui=search::topnavSubmitSearch()"); + selenium_.waitForPageToLoad(timeToWaitBetweenSearches); + assertTrue(evaluateSearchResult(selenium_, luceneQuery)); + } + int searchCounter = 1; //once already searched + + while(searchCounter<=maxSearches) { + //iterate over the seleniumList - and trigger searches via the search form + for(Selenium selenium_ : seleniumList) { + String luceneQuery = getNextSearchQuery(); + selenium_.type("ui=search::searchFormInput()", luceneQuery); + selenium_.click("ui=search::searchButton()"); + selenium_.waitForPageToLoad(timeToWaitBetweenSearches); + assertTrue(evaluateSearchResult(selenium_, luceneQuery)); + } + searchCounter++; + } + + //logout all users + for(Selenium selenium_ : seleniumList) { + selenium_.click("ui=tabs::logOut()"); + selenium_.waitForPageToLoad("30000"); + selenium_.close(); + selenium_.stop(); + } + + System.out.println("testSearch ENDED"); + } + + /** + * Get initial test data. + * + */ + private void getTestData() { + //input data - read it from property file + File propertiesFile = WorkflowHelper.locateFile(PROPERTIES_FILE_NAME); + if(propertiesFile.exists()) { + System.out.println("Read test data from properties file:"); + //read properties + Properties properties = new Properties(); + try { + FileInputStream fis = new FileInputStream(propertiesFile); + properties.load(fis); + Iterator keyIterator = properties.keySet().iterator(); + while(keyIterator.hasNext()) { + String currentKey = (String)keyIterator.next(); + String currentValue = (String)properties.get(currentKey); + if(currentKey.equals("testSpanMs")) { + testSpanMs = Long.parseLong(currentValue); + System.out.println("testSpanMs: " + currentValue); + } else if(currentKey.startsWith("user")) { + userNamesList.add(currentValue); + System.out.println("user: " + currentValue); + } else if(currentKey.startsWith("query")) { + searchQueryList.add(currentValue); + System.out.println("searchQuery: " + currentValue); + } else if (currentKey.equals("timeToWaitBetweenSearches")) { + timeToWaitBetweenSearches = currentValue; + System.out.println("timeToWaitBetweenSearches: " + timeToWaitBetweenSearches); + } else if(currentKey.equals("maxSearches")) { + maxSearches = Integer.parseInt(currentValue); + System.out.println("maxSearches: " + maxSearches); + } + } + } + catch (Exception ex) { + ex.printStackTrace(); + } + } else { + System.out.println("dummy test data"); + //testSpanMs = 60*60*1000; //1h + testSpanMs = 2*60*1000; //1h + + String[] userNames = {"test", "test2", "test3"}; + //String[] userNames = {"test"}; + String [] searchQueries = {"test", "olat", "Demo", "course"}; + + for(int i=0; i<userNames.length; i++) { + userNamesList.add(userNames[i]); + } + + for(int i=0; i<searchQueries.length; i++) { + searchQueryList.add(searchQueries[i]); + } + } + System.out.println("userNamesList: " + userNamesList); + System.out.println("searchQueryList: " + searchQueryList); + } + + /** + * Iterates over the query list over and over again. + * @return + */ + private String getNextSearchQuery() { + if(queryIterator==null || !queryIterator.hasNext()) { + queryIterator = searchQueryList.iterator(); + } + if(queryIterator.hasNext()) { + String searchQuery = queryIterator.next(); + System.out.println("getNextSearchQuery: " + searchQuery); + return searchQuery; + } + //should never return null + return null; + } + + /** + * + * @param username + * @param passwort + * @return Returns a selenium instance for the input username. + * @throws Exception + */ + private Selenium createSeleniumAndLogin(String username, String passwort) throws Exception { + OlatLoginInfos defaultOlatLoginInfos = Context.getContext().getStandardStudentOlatLoginInfos(1); + //OlatLoginInfos olatLoginInfos1 = Context.getContext().createuserIfNotExists(1, username, psw, true, false, false, false, false); + OlatLoginInfos olatLoginInfos1 = new OlatLoginInfos(defaultOlatLoginInfos.getSeleniumHostname(), + defaultOlatLoginInfos.getSeleniumBrowserId(), + defaultOlatLoginInfos.getFullOlatServerUrl(), + username, passwort); + Selenium selenium1 = Context.getContext().createSeleniumAndLogin(olatLoginInfos1); + return selenium1; + } + + /** + * We consider that an successful search should find at least a result entry. + * If no result found or service not available - this is regarded as an invalid search result. + * @param selenium_ + */ + private boolean evaluateSearchResult(Selenium selenium_, String luceneQuery) { + boolean noResults = selenium_.isTextPresent(NO_RESULTS_FOUND); + boolean resultsFound = selenium_.isTextPresent(RESULTS_FOUND); + boolean serviceNotAvailable = selenium_.isTextPresent(SERVICE_NOT_AVAILABLE_MSG); + boolean searchResultsFound = !serviceNotAvailable && (resultsFound && !noResults ); + System.out.println("searchResultsFound: " + searchResultsFound + " for query: " + luceneQuery); + System.out.println("serviceNotAvailable: " + serviceNotAvailable); + System.out.println("resultsFound: " + resultsFound); + System.out.println("noResults: " + noResults); + return searchResultsFound; + } + +} diff --git a/src/test/java/org/olat/test/functional/search/searchTest.properties b/src/test/java/org/olat/test/functional/search/searchTest.properties new file mode 100644 index 0000000000000000000000000000000000000000..6d4c23adb67b486061d70cc4c2613bbf5b7036f0 --- /dev/null +++ b/src/test/java/org/olat/test/functional/search/searchTest.properties @@ -0,0 +1,24 @@ +# MultiUserSearchTest test configuration + +#test span in milliseconds +#testSpanMs=3600000 +testSpanMs=60000 + +#timeToWaitBetweenSearches in milliseconds +timeToWaitBetweenSearches=120000 + +#max. number of searches before logout +maxSearches=5 + +#users - the key must start with the same "user" prefix +user1=seleniumstudent1 +user2=seleniumstudent2 +user3=seleniumstudent3 + +#search queries - the key must start with the "query" prefix - this should lead to at least 1 result for a student +query1=Assessment Tool Test +query2=CareOL +query3=Psychopathology +query4=Psychologie +query5=olat +query6=portlet \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/test/ChangeTstInEditor.java b/src/test/java/org/olat/test/functional/test/ChangeTstInEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..d97375cc022d1102796e667a9b13bdf9228c4b10 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/ChangeTstInEditor.java @@ -0,0 +1,72 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.qti.FIBQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Change test in test editor, part of test suite TestEditorCombiTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. author edits test TEST_NAME<br/> + * 2. author checks if only section and only item are not deletable. <br/> + * 3. Author copies question, deletes question. <br/> + * 4. Author saves test. <br/> + * + * @author sandra + * + */ + +public class ChangeTstInEditor extends BaseSeleneseTestCase { + + @Test(dependsOnGroups = {TestEditorCombiTest.FIRST}, groups = {TestEditorCombiTest.SECOND}) + public void testChangeTstInEditor() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + //author starts test from before + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + LearningResources learningResources = olatWorkflow.getLearningResources(); + LRDetailedView lRDetailedView = learningResources.searchMyResource(TestEditorCombiTest.TEST_NAME); + //edit Test + TestEditor testEditor = lRDetailedView.editTestContent(); + // gets info of not having saved + SeleniumHelper.waitUntilTextPresent(lRDetailedView.getSelenium(), "The test/questionnaire was not saved to learning resources during the last session.", 20); + // author sets passing score, tries to delete an only section, adds section and tries to delete only item + testEditor.setNecessaryPassingScore(4.0); + testEditor.selectSection("Test section"); + testEditor.deleteUndeleteable(true); + + testEditor.addSection("Second section"); + testEditor.selectQuestion("New question"); + testEditor.deleteUndeleteable(false); + + //author copies and deletes items + testEditor.selectSection("Test section"); + testEditor.selectQuestion("Gap Text Question"); + QuestionEditor questionEditor = testEditor.copyCurrentQuestion("Gap Text Question"); + questionEditor.setQuestionTitle("Second Gap"); + FIBQuestionEditor fIBQuestionEditor =(FIBQuestionEditor)testEditor.selectQuestion("Second Gap"); + questionEditor.selectQuestionAndAnswersTab(); + fIBQuestionEditor.changeCapitalization(2); + testEditor.selectSection("Second section"); + testEditor.selectQuestion("New question"); + testEditor.deleteCurrentNode(true); + testEditor.isTextPresent("New question"); + + testEditor.close(); + + } + } + diff --git a/src/test/java/org/olat/test/functional/test/CheckTestAttempts.java b/src/test/java/org/olat/test/functional/test/CheckTestAttempts.java new file mode 100644 index 0000000000000000000000000000000000000000..8c6b733408a404dd4f11e98570b095ac7f0ca29c --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/CheckTestAttempts.java @@ -0,0 +1,123 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.TestElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentForm; +import org.olat.test.util.selenium.olatapi.course.run.AssessmentTool; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Tests attempts settings of a test integrated in a course. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Author creates test TEST_NAME and integrates it in course COURSE_NAME. <br/> + * 2. First configuration: only one attempt. <br/> + * 3. Check if student can solve test only once. <br/> + * 4. Second configuration: Authors changes assessment form of student and sets attempts to zero. <br/> + * 5. Student can solve test once again. <br/> + * 6. Third configuration: Change attempts config in course editor to 2 attempts. <br/> + * 7. Check if user gets message to relaunch course and that he can solve test again.<br/> + * + * + * @author sandra + * + */ + +public class CheckTestAttempts extends BaseSeleneseTestCase { + + private final String TEST_NAME = "CheckTestAttemptsTest_" + System.currentTimeMillis(); + private final String TEST_DESCRIPTION = "CheckTestAttemptsTestDesc_" + System.currentTimeMillis(); + private final String COURSE_NAME = "CheckTestAttemptsCourseDesc_" + System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CheckTestAttemptsCourse_"+System.currentTimeMillis(); + private final String GROUP_NAME = "AttemptsGroup"; + private final String TEST_NODE_NAME = "Test1"; + + public void testIntegrateTestAndCheckAttempts() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + // author creates simple test + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflow.getLearningResources().createTestAndStartEditing(TEST_NAME, TEST_DESCRIPTION); + testEditor.setNecessaryPassingScore(1.0); + testEditor.close(); + + // author creates course, adds test, configures test with one attempt, publish + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + TestElementEditor testElementEditor = (TestElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TEST, true,TEST_NODE_NAME); + testElementEditor.chooseMyFile(TEST_NAME); + testElementEditor.configureTestLayout(null, null, false, false, 1, true); + courseEditor.publishCourse(); + LRDetailedView lRDetailedView1 = courseEditor.closeToLRDetailedView(); + CourseRun courseRunAuthor = lRDetailedView1.showCourseContent(); + + //author creates learning group and adds student + courseRunAuthor.getGroupManagement().createGroupAndAddMembers(GROUP_NAME, context.getStandardAuthorOlatLoginInfos().getUsername(), context.getStandardStudentOlatLoginInfos().getUsername()); + + // student starts course + OLATWorkflowHelper olatWorkflow1 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos()); + + LearningResources learningResources = olatWorkflow1.getLearningResources(); + CourseRun courseRunStudent = learningResources.searchAndShowCourseContent(COURSE_NAME); + + // student starts and finishes test + TestElement testElement = courseRunStudent.selectTest(TEST_NODE_NAME); + TestRun testRun = testElement.startTest(); + testElement = testRun.finishTest(true, 0); + + //select course element again, check if he cannot start test anymore + testElement = courseRunStudent.selectTest(TEST_NODE_NAME); + assertEquals("0.000", testElement.getAchievedScore()); + assertEquals("Failed", testElement.getStatus()); + assertTrue(testElement.isShowResultsPresent()); + assertTrue(testElement.cannotStartTestAnymore()); + + //author opens assessment tool and sets attempt for student to zero + AssessmentTool assessmentTool = courseRunAuthor.getAssessmentTool(); + AssessmentForm assessmentForm = assessmentTool.getAssessmentFormAsPerUser(context.getStandardStudentOlatLoginInfos().getUsername(),TEST_NODE_NAME); + assessmentForm.setAttempts(0); + assessmentForm.save(); + assessmentForm.close(); + + //check if student can solve test for the second time now + testElement = courseRunStudent.selectTest(TEST_NODE_NAME); + TestRun testRun2 = testElement.startTest(); + testElement = testRun2.finishTest(true, 0); + testElement = courseRunStudent.selectTest(TEST_NODE_NAME); + assertEquals("0.000", testElement.getAchievedScore()); + assertEquals("Failed", testElement.getStatus()); + + //check that student cannot solve test any more + assertTrue(testElement.cannotStartTestAnymore()); + + //author opens course editor, sets max. number of attempts to 2 and publishes + CourseEditor courseEditor2 = courseRunAuthor.getCourseEditor(); + TestElementEditor testElementEditor2 = (TestElementEditor)courseEditor2.selectCourseElement(TEST_NODE_NAME); + testElementEditor2.configureTestLayout(null, null, false, false, 2, true); + courseEditor2.publishCourse(); + + Thread.sleep(10000); + //student should restart course after publish and can solve test once more. + courseRunStudent.getDisposedCourseRun().closeCourseAndRestart(); + testElement = courseRunStudent.selectTest(TEST_NODE_NAME); + TestRun testRun3 = testElement.startTest(); + testElement = testRun3.finishTest(true, 0); + assertEquals("0.000", testElement.getAchievedScore()); + assertEquals("Failed", testElement.getStatus()); + assertTrue(testElement.cannotStartTestAnymore()); + + } + } + diff --git a/src/test/java/org/olat/test/functional/test/CombiQuestionnaireTest.java b/src/test/java/org/olat/test/functional/test/CombiQuestionnaireTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1b24e66ceffa7f7279869ce5338cfdf349512239 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/CombiQuestionnaireTest.java @@ -0,0 +1,40 @@ +package org.olat.test.functional.test; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Combi test for questionnaire editor and attempts check. See respective test classes for extensive documentation. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. CreateQuestionnaireWithAllQuestionTypes.java creates a questionnaire with all kinds of question types. <br/> + * 2. IntegrateQuestionnaireAndCheckAttempts.java adds the questionnaire element to a course and tests the different configurations in the questionnaire run. <br/> + * + * @author sandra + * + */ + +public class CombiQuestionnaireTest extends TestSuite { + + protected final static String QUESTIONNAIRE_NAME = "QuestionnaireAttempts"+System.currentTimeMillis(); + protected final static String QUESTIONNAIRE_DESCRIPTION = "QuestionnaireAttemptsDesc"; + protected final static String COURSE_NAME = "QuestionnaireAttemptsCourse"+System.currentTimeMillis(); + protected final static String COURSE_DESCRIPTION = "QuestionnaireAttemptsCourseDesc"; + + public static Test suite() { + TestSuite suite = new TestSuite("CombiQuestionnaireTest"); + + suite.addTestSuite(CreateQuestionnaireWithAllQuestionTypes.class); + suite.addTestSuite(IntegrateQuestionnaireAndCheckAttempts.class); + + return suite; + } + +} diff --git a/src/test/java/org/olat/test/functional/test/CreateQuestionnaireWithAllQuestionTypes.java b/src/test/java/org/olat/test/functional/test/CreateQuestionnaireWithAllQuestionTypes.java new file mode 100644 index 0000000000000000000000000000000000000000..52f8a38333c04a659f613f9b8b8918c60a2ed382 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/CreateQuestionnaireWithAllQuestionTypes.java @@ -0,0 +1,87 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.qti.EssayQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.FIBQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.MCQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionnaireEditor; +import org.olat.test.util.selenium.olatapi.qti.SCQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.SectionEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor.QUESTION_TYPES; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * + * Author creates questionnaire with all question types, part of test suite CombiQuestionnaireTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Author creates questionnaire QUESTIONNAIRE_NAME and starts editing. <br/> + * 2. Author adds all four possible question types. <br/> + * 3. Author edits all question titles and adds answers options for SC and MC. <br/> + * 5. Author closes questionnaire. <br/> + * + * @author sandra + * + */ +public class CreateQuestionnaireWithAllQuestionTypes extends BaseSeleneseTestCase { + + + + public void testCreateQuestionnaireCheckAttempts() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + //author creates questionnaire + OLATWorkflowHelper olatWorkflowHelper = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + QuestionnaireEditor questionnaireEditor = olatWorkflowHelper.getLearningResources().createQuestionnaireAndStartEditing(CombiQuestionnaireTest.QUESTIONNAIRE_NAME, CombiQuestionnaireTest.QUESTIONNAIRE_DESCRIPTION); + + // adding all question types + questionnaireEditor.addQuestion(QUESTION_TYPES.MULTIPLE_CHOICE,"Multiple Choice Question"); + questionnaireEditor.addQuestion(QUESTION_TYPES.ESSAY,"Essay Question"); + questionnaireEditor.addQuestion(QUESTION_TYPES.GAP_TEXT,"Gap Text Question"); + + // editing question and answers + SectionEditor sectionEditor = questionnaireEditor.selectSection("New section"); + sectionEditor.setSectionTitle("New section", "Questionnaire section"); + + // edit single choice question + SCQuestionEditor scQuestionEditor = (SCQuestionEditor)questionnaireEditor.selectQuestion("New question"); + scQuestionEditor.setQuestionTitle("Single Choice Question"); + scQuestionEditor.selectQuestionAndAnswersTab(); + scQuestionEditor.editQuestion("Which do you think is the most famous tourist attraction in Hong Kong?"); + scQuestionEditor.editAnswer("Harbour Junk Trip", 1); + scQuestionEditor.addNewAnswer(); + scQuestionEditor.editAnswer("Victoria Peak", 2); + scQuestionEditor.addNewAnswer(); + scQuestionEditor.editAnswer("Disney Land", 3); + + // edit multiple choice question + MCQuestionEditor mcQuestionEditor = (MCQuestionEditor)questionnaireEditor.selectQuestion("Multiple Choice Question"); + mcQuestionEditor.selectQuestionAndAnswersTab(); + mcQuestionEditor.editQuestion("Which Dim Sum specialities do you like?"); + mcQuestionEditor.editAnswer("Shrimp dumplings", 1); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("Chicken feet", 2); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("Rice rolls", 3); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("Rice pudding", 4); + + // edit gap text + FIBQuestionEditor fIBQuestionEditor = (FIBQuestionEditor)questionnaireEditor.selectQuestion("Gap Text Question"); + fIBQuestionEditor.selectQuestionAndAnswersTab(); + fIBQuestionEditor.editTextFragment(1,"Which skyscraper do you like most?"); + fIBQuestionEditor.addNewBlank(); + + // edit essay question + EssayQuestionEditor essayQuestionEditor = (EssayQuestionEditor)questionnaireEditor.selectQuestion("Essay Question"); + essayQuestionEditor.selectQuestionAndAnswersTab(); + essayQuestionEditor.editQuestion("Write about your impression of the 'Symphony of Lights'" ); + + questionnaireEditor.close(); + + } +} diff --git a/src/test/java/org/olat/test/functional/test/CreateTstInEditor.java b/src/test/java/org/olat/test/functional/test/CreateTstInEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..a07414def61bce63bcf849a7035030adb39fe886 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/CreateTstInEditor.java @@ -0,0 +1,89 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.qti.FIBQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.KPrimQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.MCQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.SCQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.SectionEditor; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor.QUESTION_TYPES; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Create test in test editor, part of test suite TestEditorCombiTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. author creates test TEST_NAME. <br/> + * 2. author adds questions of the types MC, Kprim and gap text. <br/> + * 3. author edits question titles and answers and sets correct answers. <br/> + * + * @author sandra + * + */ + +public class CreateTstInEditor extends BaseSeleneseTestCase { + private final String TEST_DESCRIPTION = "TestDescription"; + + @Test(groups = {TestEditorCombiTest.FIRST}) + public void testCreateTestInEditor() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + // author creates test + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = olatWorkflow.getLearningResources().createTestAndStartEditing(TestEditorCombiTest.TEST_NAME, TEST_DESCRIPTION); + // author adds question types + testEditor.addQuestion(QUESTION_TYPES.MULTIPLE_CHOICE,"Multiple Choice Question"); + testEditor.addQuestion(QUESTION_TYPES.KPRIM,"Kprim Question"); + testEditor.addQuestion(QUESTION_TYPES.GAP_TEXT,"Gap Text Question"); + + // author edits answers and sets correct + SectionEditor sectionEditor = testEditor.selectSection("New section"); + sectionEditor.setSectionTitle("New section", "Test section"); + SCQuestionEditor scQuestionEditor = (SCQuestionEditor)testEditor.selectQuestion("New question"); + scQuestionEditor.setQuestionTitle("Single Choice Question"); + scQuestionEditor.selectQuestionAndAnswersTab(); + scQuestionEditor.editQuestion("Is Kristina expecting a boy or a girl?"); + scQuestionEditor.editAnswer("boy", 1); + scQuestionEditor.addNewAnswer(); + scQuestionEditor.editAnswer("girl", 2); + scQuestionEditor.setSingleChoiceSolution(2); + // multiple choice + MCQuestionEditor mcQuestionEditor = (MCQuestionEditor)testEditor.selectQuestion("Multiple Choice Question"); + mcQuestionEditor.selectQuestionAndAnswersTab(); + mcQuestionEditor.editQuestion("What does Kristina like for breakfast?"); + mcQuestionEditor.editAnswer("Nussbrötli", 1); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("Gipfeli", 2); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("doppelter Espresso", 3); + mcQuestionEditor.addNewAnswer(); + mcQuestionEditor.editAnswer("Latte Macchiato", 4); + mcQuestionEditor.setMultipleChoiceSolution(4); + + // Kprim question + KPrimQuestionEditor kprimQuestionEditor = (KPrimQuestionEditor)testEditor.selectQuestion("Kprim Question"); + kprimQuestionEditor.selectQuestionAndAnswersTab(); + kprimQuestionEditor.editQuestion("Which specialities are from Sweden?"); + kprimQuestionEditor.editAnswer("Princess Tarta", 1); + kprimQuestionEditor.editAnswer("Spekemat", 2); + kprimQuestionEditor.editAnswer("Klipfisk", 3); + kprimQuestionEditor.editAnswer("Koetbullar", 4); + kprimQuestionEditor.setCorrectKprimSolution(true, false, false, true); + + // Gap text + FIBQuestionEditor fIBQuestionEditor = (FIBQuestionEditor)testEditor.selectQuestion("Gap Text Question"); + fIBQuestionEditor.selectQuestionAndAnswersTab(); + fIBQuestionEditor.editTextFragment(1,"Name of Kristinas boy:"); + fIBQuestionEditor.addNewBlank(); + fIBQuestionEditor.setBlankSolution("Nils", 2); + + } +} diff --git a/src/test/java/org/olat/test/functional/test/IntegrateQuestionnaireAndCheckAttempts.java b/src/test/java/org/olat/test/functional/test/IntegrateQuestionnaireAndCheckAttempts.java new file mode 100644 index 0000000000000000000000000000000000000000..aecff173c48a67a6548d505bb52bc0859063261b --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/IntegrateQuestionnaireAndCheckAttempts.java @@ -0,0 +1,93 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.QuestionnaireElementEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.QuestionnaireElement; +import org.olat.test.util.selenium.olatapi.course.run.QuestionnaireRun; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +/** + * + * Author adds the questionnaire element to a course and tests the different configurations in the questionnaire run, part of test suite CombiQuestionnaireTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Author creates course COURSE_NAME and starts editing. <br/> + * 2. Author adds questionnaire course element and adds questionnaire QUESTIONNAIRE_NAME. <br/> + * 3. Author sets configuration options: allow menu navigation, show menu navigation, allow cancel, + * do not allow suspend. <br/> + * 5. Author publishes course. <br/> + * 6. Student opens course COURSE_NAME and starts questionnaire QUESTIONNAIRE_NAME and checks if the above + * configuration options are effective. <br/> + * 7. Student edits answers and finishes questionnaire.<br/> + * 8. Student tries to start questionnaire for the second time, check if message that questionnaire was + * already solved is shown. <br/> + * + * @author sandra + * + */ +public class IntegrateQuestionnaireAndCheckAttempts extends BaseSeleneseTestCase { + + + + + public void testCreateQuestionnaireCheckAttempts() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + // author creates course + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos(1)); + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(CombiQuestionnaireTest.COURSE_NAME, CombiQuestionnaireTest.COURSE_DESCRIPTION);; + + // author adds questionnaire + QuestionnaireElementEditor questionnaireElementEditor = (QuestionnaireElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.QUESTIONNAIRE, true, "Questionnaire"); + String questionnaireName = CombiQuestionnaireTest.QUESTIONNAIRE_NAME; + questionnaireElementEditor.chooseMyFile(questionnaireName); + + // author configures questionnaire: cancel: ok, suspend: nok and publishes + questionnaireElementEditor.configureQuestionnaireLayout(true, true, true, false); + courseEditor.publishCourse(); + + //student starts course + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos(1)); + LearningResources learningResources = olatWorkflow2.getLearningResources(); + String courseName = CombiQuestionnaireTest.COURSE_NAME; + CourseRun courseRun = learningResources.searchAndShowCourseContent(courseName); + + // student starts questionnaire and checks configuration + QuestionnaireElement questionnaireElement = courseRun.selectQuestionnaire("Questionnaire"); + QuestionnaireRun questionnaireRun = questionnaireElement.start(); + assertTrue("Assert that a cancel questionnaire button is present", questionnaireRun.isCancelPresent()); + assertFalse("Assert that a suspend questionnaire button is present", questionnaireRun.isSuspendPresent()); + + // student solves questionnaire + assertTrue(questionnaireRun.isTextPresent("Questionnaire section")); + questionnaireRun.selectMenuItem("Single Choice Question"); + questionnaireRun.setSingleChoiceSolution("Victoria Peak"); + + questionnaireRun.selectMenuItem("Multiple Choice Question"); + String[] answers = {"Shrimp dumplings","Rice pudding"}; + questionnaireRun.setMultipleChoiceSolution(answers); + + questionnaireRun.selectMenuItem("Gap Text Question"); + questionnaireRun.fillInGap("Which skyscraper do you like most?", "Bank of China Tower"); + + questionnaireRun.selectMenuItem("Essay Question"); + questionnaireRun.fillInEssay("Hmmm... difficult question..."); + + //student finishes and tries to do it once again + CourseRun courseRun2 = questionnaireRun.finish(); + + QuestionnaireElement questionnaireElement2 = courseRun2.selectQuestionnaire("Questionnaire"); + questionnaireElement2.cannotStartAnymore(); + questionnaireElement2.isTextPresent("You have already filled in this questionnaire, thank you! Questionnaires can only be filled in once."); + + + + } +} diff --git a/src/test/java/org/olat/test/functional/test/IntegrateTstInCourse.java b/src/test/java/org/olat/test/functional/test/IntegrateTstInCourse.java new file mode 100644 index 0000000000000000000000000000000000000000..20b1863c01b304cc643673a1630149838baae076 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/IntegrateTstInCourse.java @@ -0,0 +1,59 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.SelfTestElementEditor; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.TestElementEditor; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Integrate test in course editor, part of test suite TestEditorCombiTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. author creates course COURSE_NAME<br/> + * 2. author adds self test course element, selects test from CreateTstInEditor.java<br/> + * 3. author configures self test layout options: do not allow menu navigation, do not show menu navigation, + * allow cancel, allow suspend <br/> + * 4. author adds test course element, selects test from CreateTstInEditor.java <br/> + * 5. author configures test layout options: allow menu navigation default (=true?), show menu navigation default + * (=true?), do not allow cancel, do not allow suspend, maximum nr of approaches is 2, do display results on + * test starting page <br/> + * 6. author publishes course <br/> + * + * @author sandra + * + */ + +public class IntegrateTstInCourse extends BaseSeleneseTestCase { + + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + @Test(dependsOnGroups = {TestEditorCombiTest.SECOND}, groups = {TestEditorCombiTest.THIRD}) + public void testIntegrateTestInCourse() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + // author creates course + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(TestEditorCombiTest.COURSE_NAME, COURSE_DESCRIPTION); + + // author adds self-test and configures + SelfTestElementEditor selfTestElementEditor = (SelfTestElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.SELF_TEST, true, "SelfTest"); + selfTestElementEditor.chooseMyFile(TestEditorCombiTest.TEST_NAME); + selfTestElementEditor.configureSelfTestLayout(false, false, true, true); + + //author adds test and configures + TestElementEditor testElementEditor = (TestElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TEST, true, "Test"); + testElementEditor.chooseMyFile(TestEditorCombiTest.TEST_NAME); + testElementEditor.configureTestLayout(null, null, false, false, 2, true); + + courseEditor.publishCourse(); + + } +} diff --git a/src/test/java/org/olat/test/functional/test/TestEditorCombiTest.java b/src/test/java/org/olat/test/functional/test/TestEditorCombiTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aaf08bd6dd3720a969414e27aed38edb28e1ec6c --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/TestEditorCombiTest.java @@ -0,0 +1,51 @@ +package org.olat.test.functional.test; + +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import junit.framework.Test; +import junit.framework.TestSuite; +/** + * + * Combi test for test editor. See respective test classes for extensive documentation. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. CreateTstInEditor.java creates test in test editor. <br/> + * 2. ChangeTstInEditor changes test in test editor. <br/> + * 3. IntegrateTstInCourse.java integrates test in course editor. <br/> + * 4. TstRun.java tests how student solves test in test run. <br/> + * + * @author sandra + * + */ +public class TestEditorCombiTest extends TestSuite { + + + + protected final static String COURSE_NAME = "CourseTest_" + System.currentTimeMillis(); + protected final static String TEST_NAME = "TestTest_" + System.currentTimeMillis(); + + final static String FIRST = "TestEditorCombiTest.FIRST"; + final static String SECOND = "TestEditorCombiTest.SECOND"; + final static String THIRD = "TestEditorCombiTest.THIRD"; + + + public static Test suite() { + Context context = Context.setupContext("TestEditorCombiTest", SetupType.SINGLE_VM); + //context.deleteAllLearningResourcesFromMyAuthors(); + Context.tearDown(); + + TestSuite suite = new TestSuite("CombiTest"); + + suite.addTestSuite(CreateTstInEditor.class); + suite.addTestSuite(ChangeTstInEditor.class); + suite.addTestSuite(IntegrateTstInCourse.class); + suite.addTestSuite(TstRun.class); + + return suite; + } + +} diff --git a/src/test/java/org/olat/test/functional/test/TstRun.java b/src/test/java/org/olat/test/functional/test/TstRun.java new file mode 100644 index 0000000000000000000000000000000000000000..08bd7bc0e2924438c48db9069b2a955b2e2b8c29 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/TstRun.java @@ -0,0 +1,163 @@ +package org.olat.test.functional.test; + +import java.util.HashMap; +import java.util.Map; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +/** + * + * Test how student solves test in test run, part of test suite TestEditorCombiTest.java. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Student starts course COURSE_NAME.<br/> + * 2. Student starts course element self test and check if configuration of IntegrateTstInCourse.java is effective.<br/> + * 3. Student solves self test and checks if actual score is updated according to correct solutions. <br/> + * 4. Student checks if he passed test and if setting of results layout is according to configuration. <br/> + * 5. Student starts course element test and check if configuration of IntegrateTstInCourse.java is effective.<br/> + * 6. Student solves test for the first time and checks if actual score is updated according to correct solutions. <br/> + * 7. Student checks if he failed the test and if setting of results layout is according to configuration. <br/> + * 8. Student starts test for the second time and finishes without saving any results.<br/> + * 9. Student tries to start test for the third time but cannot as max. nr of attempts is 2. <br/> + * 10. Author deletes course and test. <br/> + * + * @author sandra + * + */ + +public class TstRun extends BaseSeleneseTestCase { + + /** + * <p> + * This test is part of test suite TestEditorCombiTest.java. Student solves + * self-test and test. Check the configurations made in TestCase before. + * Author deletes course and test. + * </p> + * + * @throws Exception + */ + @Test(dependsOnGroups = {TestEditorCombiTest.THIRD}) + public void testTestRun() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + // student logs in and starts course + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardStudentOlatLoginInfos()); + LearningResources learningResources = olatWorkflow.getLearningResources(); + CourseRun courseRun = learningResources.searchAndShowCourseContent(TestEditorCombiTest.COURSE_NAME); + + // student starts self-test and checks configuration + TestElement testElement = courseRun.selectTest("SelfTest"); + TestRun testRun = testElement.startTest(); + // student solves self-test + testRun.isCancelPresent(); + testRun.isSuspendPresent(); + testRun.next(); + assertTrue(testRun.isTextPresent("Second section")); + testRun.next(); + assertTrue(testRun.isTextPresent("Second Gap")); + testRun.fillInGap("Name of Kristinas boy:", "nils"); + assertTrue(testRun.isTextPresent("Actual score: 1 / 5")); + testRun.next(); + + assertTrue(testRun.isTextPresent("Gap Text Question")); + testRun.fillInGap("Name of Kristinas boy:", "nils"); + assertTrue(testRun.isTextPresent("Actual score: 1 / 5")); + + assertTrue(testRun.isTextPresent("Kprim Question")); + Map<String, Boolean> answerToCorrectMap = new HashMap<String, Boolean>(); + answerToCorrectMap.put("Princess Tarta",true); + answerToCorrectMap.put("Spekemat", false); + answerToCorrectMap.put("Klipfisk", false); + answerToCorrectMap.put("Koetbullar", true); + testRun.setKprimSolution(answerToCorrectMap); + assertTrue(testRun.isTextPresent("Actual score: 2 / 5")); + + assertTrue(testRun.isTextPresent("Multiple Choice Question")); + String[] answers = {"Nussbrötli","Latte Macchiato"}; + testRun.setMultipleChoiceSolution(answers); + assertTrue(testRun.isTextPresent("Actual score: 3 / 5")); + + assertTrue(testRun.isTextPresent("Single Choice Question")); + testRun.setSingleChoiceSolution("girl"); + assertTrue(testRun.isTextPresent("Actual score: 4 / 5")); + + TestElement testElement2 = testRun.selfTestFinishedConfirm(); + //select course element again, else could not see the changes + testElement2 = courseRun.selectTest("SelfTest"); + assertEquals("4.000", testElement2.getAchievedScore()); + assertEquals("Passed",testElement2.getStatus()); + assertFalse(testElement2.isShowResultsPresent()); + + + // student starts test and checks configuration + testElement = courseRun.selectTest("Test"); + TestRun testRun2 = testElement.startTest(); + testRun2.isCancelPresent(); + testRun2.isSuspendPresent(); + + // student solves test for the first time + testRun2.selectMenuItem("Second Gap"); + testRun2.fillInGap("Name of Kristinas boy:", "nils"); + testRun2.selectMenuItem("Gap Text Question"); + testRun2.fillInGap("Name of Kristinas boy:", "nils"); + testRun2.selectMenuItem("Kprim Question"); + Map<String, Boolean> answerToCorrectMap2 = new HashMap<String, Boolean>(); + answerToCorrectMap.put("Princess Tarta",true); + answerToCorrectMap.put("Spekemat", false); + answerToCorrectMap.put("Klipfisk", false); + answerToCorrectMap.put("Koetbullar", true); + testRun2.setKprimSolution(answerToCorrectMap2); + testRun2.selectMenuItem("Multiple Choice Question"); + String[] answers2 = {"Nussbrötli","Latte Macchiato"}; + testRun2.setMultipleChoiceSolution(answers2); + testRun2.selectMenuItem("Single Choice Question"); + testRun2.setSingleChoiceSolution("girl"); + TestElement testElement3 = testRun2.finishTest(true, 3); + //select course element again, else could not see the changes + testElement3 = courseRun.selectTest("Test"); + + assertEquals("3.000", testElement3.getAchievedScore()); + assertEquals("Failed", testElement3.getStatus()); + assertTrue(testElement3.isShowResultsPresent()); + + + // student solves test for the second time + testElement = courseRun.selectTest("Test"); + TestRun testRun3 = testElement.startTest(); + TestElement testElement4 = testRun3.finishTest(true, 0); + testElement4 = courseRun.selectTest("Test"); + assertEquals("0.000", testElement4.getAchievedScore()); + assertEquals("Failed", testElement4.getStatus()); + + + // student tries to solve test for the third time + TestElement testElement5 = courseRun.selectTest("Test"); + testElement5 = courseRun.selectTest("Test"); + assertTrue(testElement5.cannotStartTestAnymore()); + assertTrue(testElement5.isTextPresent("There are no more attempts at your disposal.")); + + + // author deletes course and test + OLATWorkflowHelper olatWorkflow2 = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + LRDetailedView lRDetailedView = olatWorkflow2.getLearningResources().searchMyResource(TestEditorCombiTest.COURSE_NAME); + try { + lRDetailedView.deleteLR(); + } catch (Exception e) {} + lRDetailedView = olatWorkflow2.getLearningResources().searchMyResource(TestEditorCombiTest.TEST_NAME); + try { + lRDetailedView.deleteLR(); + } catch (Exception e) {} + + } +} diff --git a/src/test/java/org/olat/test/functional/test/package.html b/src/test/java/org/olat/test/functional/test/package.html new file mode 100644 index 0000000000000000000000000000000000000000..c5a13650a4a2737b1ea6181118b0cfff28ddbeee --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/package.html @@ -0,0 +1,12 @@ +<html> +<head> +</head> + +<body> + +Contains tests for Test, Questionnaire learning resources. +<br/> + + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/functional/test/test_editor_combitest.html b/src/test/java/org/olat/test/functional/test/test_editor_combitest.html new file mode 100644 index 0000000000000000000000000000000000000000..e9c3ac4e36992b937591c61f38a20608524ba011 --- /dev/null +++ b/src/test/java/org/olat/test/functional/test/test_editor_combitest.html @@ -0,0 +1,1429 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link rel="selenium.base" href="" /> +<title>test_editor_create_test</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">test_editor_create_test</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>http://demo.olat.org/olat/dmz/</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Online Learning And Training</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=dmz::username()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::username()</td> + <td>author01</td> +</tr> +<tr> + <td>type</td> + <td>ui=dmz::password()</td> + <td>olat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=dmz::login()</td> + <td></td> +</tr> +<tr> + <td>assertTitle</td> + <td>OLAT - Home</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_test()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>TestTest7</td> +</tr> +<tr> + <td>click</td> + <td>ui=learningResources::dialog_description()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>Selenium Test 1</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=New section)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_section_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_section_title()</td> + <td>Test section</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_section_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=New question)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_metadata_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_metadata_title()</td> + <td>Single Choice Question</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_metadata_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_addMultipleChoice()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::toolbox_add_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_metadata_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_metadata_title()</td> + <td>Multiple Choice Question</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_metadata_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_addKprim()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::toolbox_add_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_metadata_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_metadata_title()</td> + <td>Kprim Question</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_metadata_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_addGapText()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::toolbox_add_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_metadata_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_metadata_title()</td> + <td>Gap Text Question</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_metadata_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Single Choice Question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_tabQuestionAnswers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickQuestion()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Is Kristina expecting a boy or a girl?</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>boy</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_addNewAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>girl</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setCorrectSc(indexOfAnswer=2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Multiple Choice Question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_tabQuestionAnswers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickQuestion()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>What does Kristina like for breakfast?</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswerMc(indexOfAnswer=1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Nussbrötli</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_addNewAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswerMc(indexOfAnswer=2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Gipfeli</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_addNewAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswerMc(indexOfAnswer=3)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>doppelter Espresso</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_addNewAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswerMc(indexOfAnswer=4)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Latte Macchiato</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setCorrectMc(indexOfAnswer=4)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Kprim Question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_tabQuestionAnswers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickQuestion()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Which specialities are from Sweden?</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Princess Tarta</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Spekemat</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=3)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Klipfisk</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickAnswer(indexOfAnswer=4)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Koetbullar</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=4)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=2)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=3)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Gap Text Question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_tabQuestionAnswers()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_clickTextElement(indexOfTextElement=1)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_questionField()</td> + <td>Name of Kristinas boy:</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_editMaterial_saveAndback()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_addNewBlank()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_questionAnswers_blankField(indexOfElement=2)</td> + <td>Nils</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_save()</td> + <td></td> +</tr> +<tr> + <td></td> + <td>TODO</td> + <td></td> +</tr> +<!--new sections, move, copy, delete items--> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_clickCourseEntry(nameOfCourse=TestTest7)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_learningResource_editContent()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=TestTest7)</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_test_necessaryPassingScore()</td> + <td>4.0</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_test_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Test section)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_Change_changeDelete()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Section cannot be deleted.</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::dialog_clickOk()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_addSection()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_section_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_section_title()</td> + <td>Second section</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_section_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=New question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_Change_changeDelete()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Question cannot be deleted.</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::dialog_clickOk()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Test section)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Gap Text Question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_Change_changeCopy()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_add_save()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_metadata_title()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=testEditor::content_metadata_title()</td> + <td>Second gap</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_metadata_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_tabQuestionAnswers()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=testEditor::content_questionAnswers_capitalization(indexOfElement=2)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::content_questionAnswers_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=Second section)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::menu_link(link=New question)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_Change_changeDelete()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::dialog_clickYes()</td> + <td></td> +</tr> +<tr> + <td>assertTextNotPresent</td> + <td>New question</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=testEditor::dialog_clickSave()</td> + <td></td> +</tr> +<!--author creates course and inserts test--> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::toolbox_create_course()</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_title()</td> + <td>CourseForTest</td> +</tr> +<tr> + <td>type</td> + <td>ui=learningResources::dialog_description()</td> + <td>I don't know what to type here</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::dialog_startYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertSelfTest()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbSelfTest_chooseFile()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::commons_chooseLr_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::commons_chooseLr_chooseTest(nameOfTest=TestTest7)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbSelfTest_layoutParameters_allowCancelYes()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbSelfTest_layoutParameters_allowSuspendYes()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigationNo()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigationNo()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbSelfTest_layoutParameters_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertTest()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbTest_tabTestConfiguration()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbTest_chooseFile()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::commons_chooseLr_myEntries()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::commons_chooseLr_chooseTest(nameOfTest=TestTest7)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_allowCancelNo()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_allowSuspendNo()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_maximumNrOfApproach()</td> + <td>label=2 x</td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_displayresultsOnTestHomepageYes()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::content_bbTest_layoutParameters_save()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_publish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_selectall()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_next()</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td></td> +</tr> +<tr> + <td>select</td> + <td>ui=courseEditor::publishDialog_courseAccessDropDown()</td> + <td>label=All registered OLAT users</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::publishDialog_finish()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=courseEditor::toolbox_editorTools_closeEditor()</td> + <td></td> +</tr> +<tr> + <td></td> + <td>TODO</td> + <td></td> +</tr> +<!--student runs test--> +<tr> + <td>clickAndWait</td> + <td>ui=tabs::learningResources()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::menu_courses()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=learningResources::content_showContentOfLearningResource(nameOfLearningResource=CourseForTest)</td> + <td></td> +</tr> +<!--start with self-test--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Self-test)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::start()</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>ui=qti::cancelTest()</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>ui=qti::suspendTest()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::next()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Second section</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::next()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Second gap</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=qti::testGapItemFormElement(text=Name of Kristinas boy:)</td> + <td>nils</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Actual score: 1 / 5</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::next()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Gap Text Question</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=qti::testGapItemFormElement(text=Name of Kristinas boy:)</td> + <td>nils</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Actual score: 1 / 5</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Kprim Question</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementPlus(text=Princess Tarta)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementMinus(text=Spekemat)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementMinus(text=Klipfisk)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementPlus(text=Koetbullar)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Actual score: 2 / 5</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Multiple Choice Question</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=Nussbrötli)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=Latte Macchiato)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Actual score: 3 / 5</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Single Choice Question</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=girl)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Actual score: 4 / 5</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Your results were saved.</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::closeTest()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Self-test)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>4.000</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Passed</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=qti::showHideResults(text=Show results)</td> + <td></td> +</tr> +<!--continue with test first run--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Test)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=commons::start()</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=qti::cancelTest()</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=qti::suspendTest()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::menuItem(titleOfItem=Second gap)</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=qti::testGapItemFormElement(text=Name of Kristinas boy:)</td> + <td>nils</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::menuItem(titleOfItem=Gap Text Question)</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>ui=qti::testGapItemFormElement(text=Name of Kristinas boy:)</td> + <td>nils</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::menuItem(titleOfItem=Kprim Question )</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementPlus(text=Princess Tarta)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementMinus(text=Spekemat)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementPlus(text=Klipfisk)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testKprimItemFormElementMinus(text=Koetbullar)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::menuItem(titleOfItem=Multiple Choice Question )</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=Nussbrötli)</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=Latte Macchiato)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::menuItem(titleOfItem=Single Choice Question )</td> + <td></td> +</tr> +<tr> + <td>click</td> + <td>ui=qti::testItemFormElement(text=girl)</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::saveAnswer()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::finishTest()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Your results were saved</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::closeTest()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Test)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>3.000</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Failed</td> + <td></td> +</tr> +<tr> + <td>assertElementPresent</td> + <td>ui=qti::showHideResults(text=Show results)</td> + <td></td> +</tr> +<tr> + <td></td> + <td></td> + <td></td> +</tr> +<!--run test for second time--> +<tr> + <td>clickAndWait</td> + <td>ui=commons::start()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::finishTest()</td> + <td></td> +</tr> +<tr> + <td>waitForTextPresent</td> + <td>Your results were saved</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=qti::closeTest()</td> + <td></td> +</tr> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Test)</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>0.000</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>Failed</td> + <td></td> +</tr> +<!--run test for third time--> +<tr> + <td>clickAndWait</td> + <td>ui=course::menu_link(link=Test)</td> + <td></td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>ui=commons::start()</td> + <td></td> +</tr> +<tr> + <td>assertTextPresent</td> + <td>You cannot launch this test anymore.</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/src/test/java/org/olat/test/functional/usermanagement/DeleteUserTest.java b/src/test/java/org/olat/test/functional/usermanagement/DeleteUserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..24a32ab4ec39ff3c39ce999b67759a2d141095b7 --- /dev/null +++ b/src/test/java/org/olat/test/functional/usermanagement/DeleteUserTest.java @@ -0,0 +1,68 @@ +package org.olat.test.functional.usermanagement; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + + +/** + * + * Test if deleted user cannot login anymore. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Administrator opens user management. <br/> + * 2. Administrator creates user USER_NAME. <br/> + * 3. User USER_NAME logs in and out. <br/> + * 4. Administrator deletes user USER_NAME and check that user cannot be found anymore. <br/> + * 5. USER_NAME asserts that he cannot login anymore. <br/> + * + * @author sandra + * + */ + +public class DeleteUserTest extends BaseSeleneseTestCase { + + private final String USER_NAME = "usertodelete" + System.currentTimeMillis(); + private final String USER_FNAME = "First"; + private final String USER_LNAME = "Last"; + private final String USER_EMAIL = System.currentTimeMillis() + "@user.com"; + private final String USER_PW = "olat3"; + + + + public void testDeleteUser() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + UserManagement userManagement = olatWorkflowAdmin.getUserManagement(); + + //create user + userManagement.createUser(USER_NAME, USER_FNAME, USER_LNAME, USER_EMAIL, USER_PW); + + // log in user + OLATWorkflowHelper olatWorkflowUserToDelete = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + olatWorkflowUserToDelete.getHome(); + olatWorkflowUserToDelete.logout(); + + //admin deletes user and check that user cannot be found anymore + assertTrue(userManagement.searchUser(USER_NAME)); + boolean userDeleted = userManagement.deleteUserImmediately(USER_NAME); + Thread.sleep(5000); + if(userDeleted) { + assertFalse("Asserts that no user is found with this username: " + USER_NAME,userManagement.searchUser(USER_NAME)); + + // check that user cannot login any more + assertTrue("Asserts that the USER_NAME cannot login anymore!",OlatLoginHelper.loginExpectingError(1, USER_NAME, USER_PW)); + } else { + System.out.println("Could not delete user since the delete user workflow is locked!");//e.g. if running against OLATNG + } + olatWorkflowAdmin.logout(); + } +} + diff --git a/src/test/java/org/olat/test/functional/usermanagement/ImportUserTest.java b/src/test/java/org/olat/test/functional/usermanagement/ImportUserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1fea1be68e7ffd6b1094e025ae16985e8299c8bd --- /dev/null +++ b/src/test/java/org/olat/test/functional/usermanagement/ImportUserTest.java @@ -0,0 +1,84 @@ +package org.olat.test.functional.usermanagement; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Import users, assert that existing users don't get imported. + * <br/> + * Test setup: <br/> + * 1. Concatenate strings with all user attributes for user import. + * <p> + * Test case: <br/> + * 1. Administrator opens user management. <br/> + * 2. Admin imports NEW_USER_NAME1. <br/> + * 3. Admin imports multiple new users. <br/> + * 4. Admin imports one existing user and checks that existing user cannot be imported. <br/> + * 5. Admin imports one new and one existing user and checks that only new users can be imported. <br/> + * 6. Imported users check if the can all log in. <br/> + * + * @author sandra + * + */ + +public class ImportUserTest extends BaseSeleneseTestCase { + + private final String NEW_USER_NAME1 = "newuser1" + System.currentTimeMillis(); + private final String NEW_USER_NAME2 = "newuser2" + System.currentTimeMillis(); + private final String NEW_USER_NAME3 = "newuser3" + System.currentTimeMillis(); + private final String NEW_USER_NAME4 = "newuser4" + System.currentTimeMillis(); + private final String USER_FNAME = "First"; + private final String USER_LNAME = "Last"; + private final String USER_EMAIL = System.currentTimeMillis() + "@user1.com"; + private final String USER_EMAIL2 = System.currentTimeMillis() + "@user2.com"; + private final String USER_EMAIL3 = System.currentTimeMillis() + "@user3.com"; + private final String USER_EMAIL4 = System.currentTimeMillis() + "@user4.com"; + private final String USER_PW = "olat3"; + + private final String NEW_USER_TO_IMPORT = NEW_USER_NAME1 + " " + USER_PW + " en " + USER_FNAME + " " + USER_LNAME + " " + USER_EMAIL; + private final String MORETHANONE_NEW_USER_TO_IMPORT = NEW_USER_NAME2 + " " + USER_PW + " en " + USER_FNAME + " " + USER_LNAME + " " + USER_EMAIL2 + "\n"+ + NEW_USER_NAME3 + " " + USER_PW + " en " + USER_FNAME + " " + USER_LNAME + " " + USER_EMAIL3; + private final String NEW_AND_EXISTING_USER_TO_IMPORT = NEW_USER_TO_IMPORT + "\n" + + NEW_USER_NAME4 + " " + USER_PW + " en " + USER_FNAME + " " + USER_LNAME + " " + USER_EMAIL4;; + + public void testUserImport() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + UserManagement userManagement = olatWorkflow.getUserManagement(); + + //case 1: import one new user from excel string + assertTrue(userManagement.importAllUsers(NEW_USER_TO_IMPORT)); + + // case 2: import multiple new users from excel string + assertTrue(userManagement.importAllUsers(MORETHANONE_NEW_USER_TO_IMPORT)); + + // case 3: try to import one existing user, assert that existing user cannot be imported + assertTrue(userManagement.importUsersExpectingError(NEW_USER_TO_IMPORT)); + + // case 4: try to import one new user and one existing user + assertTrue(userManagement.importOnlyNewUsers(NEW_AND_EXISTING_USER_TO_IMPORT)); + + // check that newly imported users can log in. + OLATWorkflowHelper olatWorkflowImportedUser1 = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, NEW_USER_NAME1, USER_PW)); + olatWorkflowImportedUser1.getHome(); + olatWorkflowImportedUser1.logout(); + + OLATWorkflowHelper olatWorkflowImportedUser2 = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, NEW_USER_NAME2, USER_PW)); + olatWorkflowImportedUser2.getHome(); + olatWorkflowImportedUser2.logout(); + + OLATWorkflowHelper olatWorkflowImportedUser3 = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, NEW_USER_NAME3, USER_PW)); + olatWorkflowImportedUser3.getHome(); + olatWorkflowImportedUser3.logout(); + + OLATWorkflowHelper olatWorkflowImportedUser4 = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, NEW_USER_NAME4, USER_PW)); + olatWorkflowImportedUser4.getHome(); + olatWorkflowImportedUser4.logout(); + } +} + diff --git a/src/test/java/org/olat/test/functional/usermanagement/UserRolesTest.java b/src/test/java/org/olat/test/functional/usermanagement/UserRolesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8593b33f907ef61ee0443bbb560f9f1b9ee6d1e6 --- /dev/null +++ b/src/test/java/org/olat/test/functional/usermanagement/UserRolesTest.java @@ -0,0 +1,131 @@ +package org.olat.test.functional.usermanagement; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.selenium.olatapi.user.UserSettings; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Test if user roles can be changed and the changes apply for user. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Administrator opens user management. <br/> + * 2. Admin creates user USER_NAME. <br/> + * 3. Admin selects USER_NAME and sets role to author. <br/> + * 4. User USER_NAME logs in and checks if he has the according authoring rights but no rights for administrator, + * group and user management. <br/> + * 5. Admin resets roles, USER_NAME checks if he has no authoring rights anymore. <br/> + * 6. Admin sets roles to user manager. <br/> + * 7. USER_NAME logs in and checks if he has rights for user administration (edit other users but no admins).<br/> + * 8. Admin sets roles to group manager. <br/> + * 9. USER_NAME logs in and checks if he has rights for group administration.<br/> + * 10. Admin sets roles to system administrator. <br/> + * 11. USER_NAME logs in and checks if he has access to all administration and management tabs.<br/> + * 12. Admin resets roles. <br/> + * 13. USER_NAME logs in and checks if he has no more authoring, manager or administrator rights on the system. <br/> + * + * @author sandra + * + */ + +public class UserRolesTest extends BaseSeleneseTestCase { + + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + //private final String USER_NAME = "usermngt_testuser" + System.currentTimeMillis(); + private final String USER_NAME = "usermngttestuser" + System.currentTimeMillis(); + + private final String USER_FNAME = "First"; + private final String USER_LNAME = "Last"; + private final String USER_EMAIL = System.currentTimeMillis() + "@user.com"; + private final String USER_PW = "TestuserPW1"; + + + public void testUserRoles() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + UserManagement userManagement = olatWorkflow.getUserManagement(); + + //create user + userManagement.createUser(USER_NAME, USER_FNAME, USER_LNAME, USER_EMAIL, USER_PW); + + // search and select user + UserSettings userSettings = olatWorkflow.getUserManagement().selectUser(USER_NAME); + + // change role: author + userSettings.setRoles(false, false, true, false, false); + + // log in user and check if he has authoring rights, but not tabs group management, user management, administration + OLATWorkflowHelper olatWorkflowAuthor = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertTrue(olatWorkflowAuthor.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + assertFalse(olatWorkflowAuthor.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertFalse(olatWorkflowAuthor.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertFalse(olatWorkflowAuthor.getSelenium().isElementPresent("ui=tabs::administration()")); + olatWorkflowAuthor.logout(); + + // uncheck author role and make sure user has no more authoring rights after login + userSettings.setRoles(false, false, false, false, false); + + // login user, make sure he cannot create course, no tabs group management, user management, administration + OLATWorkflowHelper olatWorkflowStudent = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertFalse(olatWorkflowStudent.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + assertFalse(olatWorkflowStudent.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertFalse(olatWorkflowStudent.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertFalse(olatWorkflowStudent.getSelenium().isElementPresent("ui=tabs::administration()")); + olatWorkflowStudent.logout(); + + // allocate user manager role + userSettings.setRoles(true, false, false, false, false); + + //login user manager, can create course, has tab user management, but not group management and administration + OLATWorkflowHelper olatWorkflowUserManager = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertFalse(olatWorkflowUserManager.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + assertTrue(olatWorkflowUserManager.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertFalse(olatWorkflowUserManager.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertFalse(olatWorkflowUserManager.getSelenium().isElementPresent("ui=tabs::administration()")); + + //can edit student but not admin + UserSettings studentSettings = olatWorkflowUserManager.getUserManagement().selectUser(context.getStandardStudentOlatLoginInfos().getUsername()); + studentSettings.isTextPresent(USER_NAME); + assertTrue("Asserts that the current user doesn't not have enough rights to edit user", olatWorkflowUserManager.getUserManagement().cannotEditUser(context.getStandardAdminOlatLoginInfos().getUsername())); + olatWorkflowUserManager.logout(); + + // allocate group manager role + userSettings.setRoles(false, true, false, false, false); + + //login group manager, can create course, has tab group management, but not user management and administration + OLATWorkflowHelper olatWorkflowGroupManager = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertTrue(olatWorkflowGroupManager.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertFalse(olatWorkflowGroupManager.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertFalse(olatWorkflowGroupManager.getSelenium().isElementPresent("ui=tabs::administration()")); + assertFalse(olatWorkflowGroupManager.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + olatWorkflowGroupManager.logout(); + + // allocate admin role + userSettings.setRoles(false, false, false, true, false); + + // log in admin, can create course, has all tabs + OLATWorkflowHelper olatWorkflowAdmin = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertTrue(olatWorkflowAdmin.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + assertTrue(olatWorkflowAdmin.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertTrue(olatWorkflowAdmin.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertTrue(olatWorkflowAdmin.getSelenium().isElementPresent("ui=tabs::administration()")); + olatWorkflowAdmin.logout(); + + // uncheck all roles and make sure user has no more rights after login + userSettings.setRoles(false, false, false, false, false); + OLATWorkflowHelper olatWorkflowNoRights = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW)); + assertFalse(olatWorkflowNoRights.getLearningResources().getSelenium().isElementPresent("ui=learningResources::toolbox_create_course()")); + assertFalse(olatWorkflowNoRights.getSelenium().isElementPresent("ui=tabs::groupAdministration()")); + assertFalse(olatWorkflowNoRights.getSelenium().isElementPresent("ui=tabs::userManagement()")); + assertFalse(olatWorkflowNoRights.getSelenium().isElementPresent("ui=tabs::administration()")); + olatWorkflowNoRights.logout(); + } +} + diff --git a/src/test/java/org/olat/test/functional/usermanagement/UserSettingsTest.java b/src/test/java/org/olat/test/functional/usermanagement/UserSettingsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5231dbe12955a81934d98e96e7bc36c2b5b619a6 --- /dev/null +++ b/src/test/java/org/olat/test/functional/usermanagement/UserSettingsTest.java @@ -0,0 +1,60 @@ +package org.olat.test.functional.usermanagement; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.home.MySettings; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.selenium.olatapi.user.UserSettings; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Test if user settings can be changed in user management. + * <br/> + * Test setup: <br/> + * - + * <p> + * Test case: <br/> + * 1. Administrator opens user management and searches for user USER_NAME. <br/> + * 2. Admin changes USER_NAME's last name and password. <br/> + * 3. User USER_NAME logs in and checks if changes apply. <br/> + * + * @author sandra + * + */ + +public class UserSettingsTest extends BaseSeleneseTestCase { + + //TODO:LD: temporary changed usernames - workaround for OLAT-5249 + //private final String USER_NAME = "usermngt_testuser" + System.currentTimeMillis(); + private final String USER_NAME = "usermngttestuser" + System.currentTimeMillis(); + private final String USER_FNAME = "First"; + private final String USER_LNAME = "Last"; + private final String USER_EMAIL = System.currentTimeMillis() + "@user.com"; + private final String USER_PW = "TestuserPW1"; + private final String USER_LNAME_NEW = "LastNew"; + private final String USER_PW_NEW = "TestuserPWNew2"; + + public void testUserSettings() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OLATWorkflowHelper olatWorkflowAdmin = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos()); + UserManagement userManagement = olatWorkflowAdmin.getUserManagement(); + + //create user + userManagement.createUser(USER_NAME, USER_FNAME, USER_LNAME, USER_EMAIL, USER_PW); + + // search and select user, change first name, change password + UserSettings userSettings = olatWorkflowAdmin.getUserManagement().selectUser(USER_NAME); + userSettings.setLastName(USER_LNAME_NEW, true); + userSettings.setPassword(USER_PW_NEW); + + // log in as user, check if new password is valid + OLATWorkflowHelper olatWorkflowUser = context.getOLATWorkflowHelper(context.getOlatLoginInfo(1, USER_NAME, USER_PW_NEW)); + + // check if user's last name was changed + MySettings myNewSettings = olatWorkflowUser.getHome().getUserSettings(); + assertTrue(myNewSettings.isDisabledTextPresent(USER_LNAME_NEW)); + } +} + diff --git a/src/test/java/org/olat/test/load/LoginLoadTest.java b/src/test/java/org/olat/test/load/LoginLoadTest.java new file mode 100644 index 0000000000000000000000000000000000000000..399ea60d5e2116a8d1ddeaa2b54a82d370381f2e --- /dev/null +++ b/src/test/java/org/olat/test/load/LoginLoadTest.java @@ -0,0 +1,89 @@ +package org.olat.test.load; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * Performance test; it measures the time needed to login and logout "iterations" times, using the same browser window. <br/> + * + * Test case: <br/> + * Login/logout on one node numOfIterations times. + * + * @author lavinia + * + */ +public class LoginLoadTest extends BaseSeleneseTestCase { + + private int numOfIterations = 80; + + public void setUp() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + } + + /** + * We would like to login on 2 different nodes, but depends on the multiVmOlatUrl1, multiVmOlatUrl2 whether + * we really get to login in two different nodes. + * + * @throws Exception + */ + public void testLoginForEachNode() throws Exception { + long duration1 = loginOnOneNode(1); + long duration2 = loginOnOneNode(2); + System.out.println("$$$ login comparison - duration1: " + duration1/1000 + " s"); + System.out.println("$$$ login comparison - duration2: " + duration2/1000 + " s"); + } + + /** + * Login/logout on one node iterations times. + * + * @param nodeId + * @return + * @throws Exception + */ + private long loginOnOneNode(int nodeId) throws Exception { + long initialTime = System.currentTimeMillis(); + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos(nodeId)); + workflow.logout(); + int iterationCounter = 0; + for(int i=0; i<numOfIterations; i++) { + simpleLoginSameBrowserWindow(workflow.getSelenium(), Context.getContext().getStandardAdminOlatLoginInfos(nodeId)); + iterationCounter++; + workflow.logout(); + } + long endTime = System.currentTimeMillis(); + long duration = endTime - initialTime; + System.out.println("loginOnOneNode " + nodeId + " took: " + duration/1000 + " s --- " + iterationCounter + " times"); + return duration; + } + + /** + * + * @param selenium + * @param loginInfos + * @throws Exception + */ + private void simpleLoginSameBrowserWindow(Selenium selenium, OlatLoginInfos loginInfos) throws Exception { + String username = loginInfos.getUsername(); + String password = loginInfos.getPassword(); + + OlatLoginHelper.inputUserNameAndPassword(selenium, username, password); + int second = 0; + while(second<20) { + try { + if (selenium.isElementPresent("ui=home::menu_settings()")) //logged in + break; + } catch (Exception e) { + } + Thread.sleep(500); + second++; + } + assertTrue(selenium.isElementPresent("ui=home::menu_settings()")); + } + +} diff --git a/src/test/java/org/olat/test/load/MultiBrowserClusterEnrolmentLoadManualtest.java b/src/test/java/org/olat/test/load/MultiBrowserClusterEnrolmentLoadManualtest.java new file mode 100644 index 0000000000000000000000000000000000000000..fd4044bbd37677d492740d5a7401352fc6659e2c --- /dev/null +++ b/src/test/java/org/olat/test/load/MultiBrowserClusterEnrolmentLoadManualtest.java @@ -0,0 +1,193 @@ +package org.olat.test.load; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.EnrolmentRun; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; +import com.thoughtworks.selenium.SeleniumException; + +/** + * This is a loadtest and is therefore excluded from the nightly selenium test set. + * The name being lowercase it is excluded from the rule 'include *Test*' + * @author Stefan + * + */ +public class MultiBrowserClusterEnrolmentLoadManualtest extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + protected com.thoughtworks.selenium.Selenium selenium3; + + public void testMultiBrowserClusterNewLearningArea() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + + String standardPassword = context.getStandardStudentOlatLoginInfos().getPassword(); + OlatLoginInfos user1 = context.createuserIfNotExists(1, "enrtstusr1", standardPassword, true, true, true, true, true); + OlatLoginInfos user2 = context.createuserIfNotExists(2, "enrtstusr2", standardPassword, true, true, true, true, true); + OlatLoginInfos user3 = context.createuserIfNotExists(1, "enrtstusr3", standardPassword, true, true, true, true, true); + + // step1: make sure the limit on participants on group A is 1 + OLATWorkflowHelper workflow1; + OLATWorkflowHelper workflow2; + OLATWorkflowHelper workflow3; + { + System.out.println("logging in browser 1..."); + + workflow1 = context.getOLATWorkflowHelper(user1); + CourseRun courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_3); + + // go to group management and modify the limit on gruppe A to 1 + GroupManagement groupManagement1 = courseRun1.getGroupManagement(); + GroupAdmin editLearningGruppeA = groupManagement1.editLearningGroup("Gruppe A"); + editLearningGruppeA.removeAllWaiting(); + editLearningGruppeA.removeAllParticipants(); + editLearningGruppeA.configureParticipantsAndWaitingList(1, false, false); + editLearningGruppeA.close("Gruppe A"); + + courseRun1.close(Context.DEMO_COURSE_NAME_3); + } + + // relogin user1 step 2: log in user 2 and 3 + CourseRun courseRun1; + CourseRun courseRun2; + CourseRun courseRun3; + + { + workflow1 = context.getOLATWorkflowHelper(user1); + courseRun1 = workflow1.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_3); + + System.out.println("logging in browser 2..."); + workflow2 = context.getOLATWorkflowHelper(user2); + courseRun2 = workflow2.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_3); + + System.out.println("logging in browser 3..."); + workflow3 = context.getOLATWorkflowHelper(user3); + courseRun3 = workflow3.getLearningResources().searchAndShowCourseContent(Context.DEMO_COURSE_NAME_3); + } + + + // now spawn 3 threads all racing to get the enrolment and releasing after a random amount of time + final CourseRun[] courseRuns = new CourseRun[] {courseRun1, courseRun2, courseRun3}; + final List<String> errorList = new LinkedList<String>(); + List<Thread> l = new LinkedList<Thread>(); + for (int i=0; i<courseRuns.length; i++) { + final CourseRun courseRun = courseRuns[i]; + final int id = i; + + Thread th = new Thread(new Runnable() { + CourseRun myCourseRun = courseRun; + public void run() { + Random r = new Random(); + + while(true) { + System.out.println(id+" Nanosleep..."); + try { + Thread.sleep(r.nextInt(20)); + } catch (InterruptedException e1) { + break; + } + System.out.println(id+" Clicking on Einschreibung..."); + EnrolmentRun selectEnrolment = myCourseRun.selectEnrolment("Einschreibung"); + System.out.println(id+" Nanosleep2..."); + try { + Thread.sleep(r.nextInt(50)); + } catch (InterruptedException e1) { + break; + } + System.out.println(id + "Let's look for 'enrol'..."); + if ( ! selectEnrolment.alreadyEnrolled("Gruppe A")) { + Selenium s = null; + try{ + System.out.println(id+" Let's click 'enrol'..."); + selectEnrolment.enrol("Gruppe A"); + System.out.println(id+" We clicked enrol."); + + s = selectEnrolment.getSelenium(); + // let's see if we won or not + if (s.getBodyText().contains("In the meantime this group is complete.")) { +// if (s.isTextPresent("In the meantime this group is complete.")) { + // oh no, we lost! + System.out.println(id+" but we lost... click 'OK'"); + s.click("ui=dialog::OK()"); + try { + Thread.sleep(250); + } catch (InterruptedException e) { + break; + } + System.out.println(id+" and ocntinue..."); + continue; + } + System.out.println(id+" We got it!!!!"); + // otherwise: + // we're the winner!!! + if (!s.isTextPresent("You have already enroled for the learning group mentioned below")) { + errorList.add("enrol somehow didn't work (1)"); + return; + } + System.out.println(id+" Nanosleep 3..."); + try { + Thread.sleep(r.nextInt(200)); + } catch (InterruptedException e) { + break; + } + if (!s.isTextPresent("You have already enroled for the learning group mentioned below")) { + errorList.add("enrol somehow didn't work (2)"); + return; + } + + System.out.println(id+" cancel enrolment..."); + selectEnrolment.cancelEnrolment("Gruppe A"); + System.out.println(id+" cancel enrolment done. sleep a bit..."); + try { + Thread.sleep(r.nextInt(100)); + } catch (InterruptedException e) { + break; + } + } catch(SeleniumException e) { + // ok, someone else was quicker + + if (s != null && !s.isTextPresent("Learning group is complete")) { + errorList.add("expected 'learning group is complete' but didn't get it"); + return; + } + continue; + } + } + + } + + } + + }); + th.setDaemon(true); + th.start(); + l.add(th); + } + + + Thread.sleep(180000); + System.out.println("Stopping all threads..."); + for (Iterator<Thread> it = l.iterator(); it.hasNext();) { + Thread th = it.next(); + th.interrupt(); + System.out.println("Waiting for a thread..."); + th.join(); + System.out.println("Thread stopped."); + } + System.out.println("All threads stopped."); + assertEquals(0, errorList.size()); + } +} diff --git a/src/test/java/org/olat/test/load/OpenAllCoursesOnFirstPageTest.java b/src/test/java/org/olat/test/load/OpenAllCoursesOnFirstPageTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a9263c141da4b66d6199a9d0a4a19aaddaa50b90 --- /dev/null +++ b/src/test/java/org/olat/test/load/OpenAllCoursesOnFirstPageTest.java @@ -0,0 +1,88 @@ +package org.olat.test.load; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Performance test; it measures the time needed to open course, click few times (numOfIterations) + * in course, close course, and repeat for all courses on the first page (LearningResources/Courses). + * + * @author Lavinia Dumitrescu + * + */ +public class OpenAllCoursesOnFirstPageTest extends BaseSeleneseTestCase { + + private final int courseElemIterations = 10; + private int visitedCourseElements = 0; + private int testIterations = 3; //repeat all this times + + /** + * Open learning resources, select courses menu item select each course on first page, repeat testIteration. + * When course run is open select first courseElemIterations elements, and close course tab. + * + * @throws Exception + */ + public void testVisitAllCourses() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + LearningResources learningResources = workflow.getLearningResources(); + + long initialTime = System.currentTimeMillis(); + + //go to courses and open each course on each table page, then close the course + int iteration = 0; + int courseIndex = 1; + int visitedCourses = 0; + int pageLength = 20; + while(iteration<testIterations) { + System.out.println("iteration: " + iteration); + while(courseIndex<=pageLength) { + CourseRun courseRun = learningResources.showCourseContent(false, courseIndex); + if(courseRun!=null) { + visitCourse(courseRun); + courseIndex++; + visitedCourses++; + } else if(courseRun==null) { + courseIndex = 1; + break; + } + } + iteration++; + } + + long endTime = System.currentTimeMillis(); + long duration = endTime - initialTime; + + System.out.println("$$$$$$ testVisitAllCourses took: " + duration/1000 + " s"); + courseIndex--; + System.out.println("$$$$$$ visited courses: " + visitedCourses); + System.out.println("$$$$$$ visited course elements: " + visitedCourseElements); + } + + /** + * Select first numOfIterations elements in this course. + * + * @param courseRun + */ + public void visitCourse(CourseRun courseRun) throws Exception { + System.out.println("visit course"); + //select node in course + for(int i=1; i<=courseElemIterations; i++) { + boolean elemFound = courseRun.selectCourseElement(i); + Thread.sleep(200); + if(!elemFound) { + System.out.println("Could not select course element with index: " + i); + break; + } else { + visitedCourseElements++; + } + } + courseRun.closeAny(); + System.out.println("closed course"); + } + +} diff --git a/src/test/java/org/olat/test/load/OpenAllCoursesTest.java b/src/test/java/org/olat/test/load/OpenAllCoursesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e0e14863ec435255d9a631206ac7e3c06297f2ce --- /dev/null +++ b/src/test/java/org/olat/test/load/OpenAllCoursesTest.java @@ -0,0 +1,65 @@ +package org.olat.test.load; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * Performance test; it measures the time needed to open course, click few times (numOfIterations) + * in course, close course, and repeat for all courses. + * + * @author Lavinia Dumitrescu + * + */ +public class OpenAllCoursesTest extends BaseSeleneseTestCase { + + private final int numOfIterations = 5; + + public void testVisitAllCourses() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.TWO_NODE_CLUSTER); + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + LearningResources learningResources = workflow.getLearningResources(); + //go to courses and open each course on each table page, then close the course + boolean selectNextPage = false; + int courseIndex = 1; + int pageLength = 20; + while(courseIndex<=pageLength) { + CourseRun courseRun = learningResources.showCourseContent(selectNextPage, courseIndex); + if(courseRun!=null) { + visitCourse(courseRun); + courseIndex++; + selectNextPage = false; + } else if(courseRun==null && !learningResources.hasMorePages()) { + break; + } + if(courseIndex==21 && learningResources.hasMorePages()) { + courseIndex = 1; + selectNextPage = true; + } + } + + } + + /** + * Select first numOfIterations elements in this course. + * + * @param courseRun + */ + public void visitCourse(CourseRun courseRun) throws InterruptedException { + System.out.println("visit course"); + //select node in course + for(int i=1; i<=numOfIterations; i++) { + boolean elemFound = courseRun.selectCourseElement(i); + if(!elemFound) { + break; + } + } + Thread.sleep(3000); + courseRun.closeAny(); + System.out.println("closed course"); + } + +} diff --git a/src/test/java/org/olat/test/load/package.html b/src/test/java/org/olat/test/load/package.html new file mode 100644 index 0000000000000000000000000000000000000000..bfeb6d14dfd1a3d9bd5a7505180bb8a5e9d4a729 --- /dev/null +++ b/src/test/java/org/olat/test/load/package.html @@ -0,0 +1,11 @@ +<html> +<head> +</head> + +<body> + +Selenium load tests (that is login-logout n times, open all courses, etc), they measure how long it takes to perform these tasks. +<br/> + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/sandbox/CreateCourseTest.java b/src/test/java/org/olat/test/sandbox/CreateCourseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..17361ce6706ca179671d60c3573883996c685a05 --- /dev/null +++ b/src/test/java/org/olat/test/sandbox/CreateCourseTest.java @@ -0,0 +1,342 @@ +package org.olat.test.sandbox; + +import java.io.File; + +import org.olat.test.functional.test.TestEditorCombiTest; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.AssessmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.EnrolmentEditor; +import org.olat.test.util.selenium.olatapi.course.editor.TestElementEditor; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor.CourseElemTypes; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; +import org.olat.test.util.selenium.olatapi.course.run.QuestionnaireElement; +import org.olat.test.util.selenium.olatapi.course.run.TestElement; +import org.olat.test.util.selenium.olatapi.course.run.TestRun; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.group.GroupAdmin; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.selenium.olatapi.home.HomeConfigurator; +import org.olat.test.util.selenium.olatapi.home.MySettings; +import org.olat.test.util.selenium.olatapi.lr.CPResourceEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.lr.LearningResources.LR_Types; +import org.olat.test.util.selenium.olatapi.qti.EssayQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.FIBQuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionnaireEditor; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor.QUESTION_TYPES; +import org.olat.test.util.selenium.olatapi.user.UserManagement; +import org.olat.test.util.selenium.olatapi.user.UserSettings; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.test.util.selenium.olatapi.course.editor.QuestionnaireElementEditor; +import org.olat.test.util.selenium.OlatLoginHelper; + +/** + * Sandbox test class. + * Tests basic functionality. + * + * @author Lavinia Dumitrescu + * + */ +public class CreateCourseTest extends BaseSeleneseTestCase { + + private String COURSE_NAME = "AAA"+ System.currentTimeMillis(); + private String WIKI_NAME = "aWiki"+ System.currentTimeMillis(); + private String GROUP_NAME = "aGroup"+ System.currentTimeMillis(); + private String TEST_NAME = "aTest"+ System.currentTimeMillis(); + + public void setUp() throws Exception { + Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + } + + private void testUserManagement() { + OLATWorkflowHelper workflow_A = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + /*UserManagement userManagement = workflow_A.getUserManagement(); + UserSettings userSettings = userManagement.selectUser("lavinia"); + userSettings.setFirstName("Lavinia A.", true); + userSettings.setPassword("lavinia1"); + userSettings.setRoles(null, false, true, false, false);*/ + + /*userManagement.createUser("lavinia3", "Lavinia", "D.", "ld3@gmail.com", "lavinia3"); + + OLATWorkflowHelper workflow_L = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, "lavinia3", "lavinia3")); + workflow_L.getHome().getEvidencesOfAchievement();*/ + MySettings mySettings = workflow_A.getHome().getUserSettings(); + String email = mySettings.getEmail(); + boolean isMyLastNamePresent = mySettings.isDisabledTextPresent("Administrator"); + + //String lastname = mySettings.getDisabledText("Last name"); + System.out.println("isMyLastNamePresent: " + isMyLastNamePresent); + //System.out.println("lastname: " + lastname); + System.out.println("email: " + email); + + workflow_A.logout(); + } + + private void testUserManager() { + /*OLATWorkflowHelper workflow_A = Context.getContext().getOLATWorkflowHelper(Context.getContext().getOlatLoginInfo(1, "lavinia", "lavinia1")); + boolean cannotEditAdmin = workflow_A.getUserManagement().cannotEditUser("administrator"); + System.out.println("cannotEditAdmin: " + cannotEditAdmin);*/ + + OLATWorkflowHelper workflow_A = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + workflow_A.getUserManagement().deleteUser("test12"); + System.out.println("user deleted"); + } + + /** + * Tests basic course functionality: + * - create course + * - insert node + * - publish + * - create learning group + * @throws Exception + */ + private void testCreateCourse() throws Exception { + //OlatLoginInfos loginInfos = Context.getContext().createuserIfNotExists(1, "test102", "test100", true, true, true, true, true); + + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla"); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + CourseElementEditor courseElementEditor = courseEditor.selectCourseElement("Forum"); + courseElementEditor.setDescription("NEW DESCRIPTION"); + + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + Forum forum = courseRun.selectForum("Forum"); + forum.openNewTopic("test entry concurrent edit", "forum message editing"); + + //attach doc + /*File doc = OlatServerSetupHelper.locateFile("org/olat/test/file_resources/Word.doc"); + String remoteDoc = Context.getContext().provideFileRemotely(doc); + forum.attachFileToMsg(remoteDoc); + forum.deleteAttachedFile("Word.doc"); + + + //create group + GroupManagement groupManagement = courseRun.getGroupManagement(); + groupManagement.createLearningGroup("learning group selenium 5", "fifth lg", 1, false, false); + courseRun = groupManagement.close(); + + courseEditor = courseRun.getCourseEditor(); + EnrolmentEditor enrolmentEditor = (EnrolmentEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.ENROLMENT, true, null); + enrolmentEditor.selectLearningGroups("learning group selenium 5"); + enrolmentEditor.changeVisibilityDependingOnGroup("learning group selenium 5"); + courseEditor.publishCourse(); + */ + + workflow.logout(); + } + + private void testCreateLearningArea() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + LRDetailedView lRDetailedView1 = workflow.getLearningResources().createResource(COURSE_NAME, "bla", LR_Types.COURSE); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + GroupManagement groupManagement1 = courseRun1.getGroupManagement(); + groupManagement1.createLearningArea("learning area selenium 1", null); + workflow.logout(); + } + + private void testAssessmentElement() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla"); + AssessmentEditor assessmentEditor = (AssessmentEditor)courseEditor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, null); + // author fills in the assessment configuration form + assessmentEditor.configure(true, 1, 10, true, 5); + courseEditor.publishCourse(); + } + + private void testRunTest() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + CourseRun courseRun = workflow.getLearningResources().searchAndShowCourseContent("Demo Course"); + TestElement testElement = courseRun.selectTest("Test"); + TestRun testRun = testElement.startTest(); + testRun.finishTest(true, 0); + testElement = courseRun.selectTest("Test"); + assertEquals("0.000", testElement.getAchievedScore()); + } + + private void testCreateTest() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos()); + TestEditor testEditor = workflow.getLearningResources().createTestAndStartEditing(TEST_NAME, "nonsense"); + testEditor.addQuestion(QUESTION_TYPES.GAP_TEXT,"Gap Text Question"); + // Gap text + FIBQuestionEditor fIBQuestionEditor = (FIBQuestionEditor)testEditor.selectQuestion("Gap Text Question"); + fIBQuestionEditor.selectQuestionAndAnswersTab(); + fIBQuestionEditor.editTextFragment(1,"Name of Kristinas boy:"); + fIBQuestionEditor.addNewBlank(); + fIBQuestionEditor.setBlankSolution("Nils", 2); + fIBQuestionEditor.changeCapitalization(2); + workflow.logout(); + } + + private void testCopyCourse() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + /*LRDetailedView lRDetailedView = workflow.getLearningResources().searchResource("Demo Course", null); + lRDetailedView.copyLR("Copy A of Demo course", "bla"); + + workflow.logout();*/ + } + + /*public void testChangeAccess() throws Exception { + //OlatLoginInfos loginInfos = Context.getContext().createuserIfNotExists(1, "test102", "test100", true, true, true, true, true); + + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla"); + courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.FORUM, true, null); + CourseElementEditor courseElementEditor = courseEditor.selectCourseElement("Forum"); + + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + courseRun.getGroupManagement().createGroupAndAddMembers(GROUP_NAME, null, Context.getContext().getStandardStudentOlatLoginInfos().getUsername()); + courseEditor = courseRun.getCourseEditor(); + + //courseElementEditor.changeVisibilityDependingOnGroup("lg av 1"); + + courseElementEditor = courseEditor.insertCourseElement(CourseElemTypes.ASSESSMENT, true, null); + courseElementEditor.changeAccessyDependingOnGroup(GROUP_NAME); + courseElementEditor.editVisibilityInfo("this assessment is only accessible to learning group members"); + + courseEditor.publishCourse(); + + workflow.logout(); + }/* + + /*public void testCreateWiki() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + LRDetailedView lRDetailedView1 = workflow.getLearningResources().createResource(WIKI_NAME, "course run test", LR_Types.WIKI); + //select again the learningResources1 + LearningResources learningResources = workflow.getLearningResources(); + CourseEditor courseEditor1 = learningResources.createCourseAndStartEditing(COURSE_NAME, "course run test"); + + workflow.logout(); + }*/ + + /*public void testCreateGroup() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + Groups groupsTab = workflow.getGroups(); + GroupAdmin groupAdmin = groupsTab.createProjectGroup(GROUP_NAME, "bla bla"); + String[] owners = {Context.getContext().getStandardAuthorOlatLoginInfos().getUsername()}; + String[] participants = {Context.getContext().getStandardStudentOlatLoginInfos().getUsername()}; + groupAdmin.addMembers(participants, owners); + workflow.logout(); + }*/ + + /*public void testGroups() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + Groups groups1 = workflow.getGroups(); + GroupAdmin group = groups1.createProjectGroup(GROUP_NAME, "second test"); + group.setTitleAndDescription(GROUP_NAME + "changed", "description changed"); + group.setTools(true, true, true, true, true, true); + group.setInfo("hello everybody"); + group.selectCalendarWriteAccess("Owners and tutors respectively"); + String[] userNames = {Context.getContext().getStandardStudentOlatLoginInfos().getUsername()}; + group.addMembers(userNames, new String[0]); + workflow.logout(); + }*/ + + private void testCreateQuestionnaire() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos()); + + WorkflowHelper.deleteAllLearningResourcesFromAuthor(Context.getContext().getStandardAuthorOlatLoginInfos().getUsername()); + QuestionnaireEditor qEditor = workflow.getLearningResources().createQuestionnaireAndStartEditing(TEST_NAME, "nonsense"); + EssayQuestionEditor questionEditor = (EssayQuestionEditor)qEditor.addQuestion(QUESTION_TYPES.ESSAY,"ESSAY"); + questionEditor.selectQuestionAndAnswersTab(); + questionEditor.editQuestion("please describe ..."); + questionEditor.setAnswerSize(120, 11); + qEditor.close(); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla bla"); + QuestionnaireElementEditor questionnaireElementEditor= (QuestionnaireElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.QUESTIONNAIRE, true, null); + questionnaireElementEditor.chooseMyFile("aTest1253791768388"); + questionnaireElementEditor.configureQuestionnaireLayout(true, true, true, true); + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + QuestionnaireElement questionnaireElement = courseRun.selectQuestionnaire(CourseEditor.QUESTIONNAIRE_TITLE); + questionnaireElement.start().finish(); + } + + private void testLoginExpectingError() throws Exception { + assertTrue(OlatLoginHelper.loginExpectingError(1, "test4", "test")); + } + + private void testForum() { + // author creates course with forum, opens welcome message topic + OLATWorkflowHelper olatWorkflow_1 = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAuthorOlatLoginInfos()); + CourseEditor courseEditor1 = olatWorkflow_1.getLearningResources().createCourseAndStartEditing("Concurrent_Forum_Replies_1260951770640", "selenium"); + courseEditor1.insertCourseElement(CourseElemTypes.FORUM, true, null); + courseEditor1.publishCourse(); + LRDetailedView lRDetailedView1 = courseEditor1.closeToLRDetailedView(); + CourseRun courseRun1 = lRDetailedView1.showCourseContent(); + Forum forum1 = courseRun1.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + forum1.openNewTopic("welcome", "werdet euren senf los"); + } + + private void testMyGroupPortletConfig() { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + workflow.getHome().getHomeConfigurator().configMyGroupPortlet(99, HomeConfigurator.SORT_TYPE.ALPHABET, true); + workflow.getHome().getHomeConfigurator().configMyBookmarkPortlet(99, HomeConfigurator.SORT_TYPE.ALPHABET, true); + } + + private void testImportCP() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + try { + File f = WorkflowHelper.locateFile("org/olat/test/sandbox/UserManual_6.2.zip"); + CPResourceEditor cpEditor = workflow.getLearningResources().importCP(f, "A_B12_CP", "BLA BLA"); + + if(cpEditor!=null) { + cpEditor.addPageAndRename("Introduction", "Lavinia", "bau bau"); + cpEditor.copyPageAndRename("Introduction", "SecondIntroduction"); + cpEditor.copyPageAndRename("Lavinia", "Dora"); + cpEditor.copyPageAndRename("Dora", "ET"); + + cpEditor.deletePage("Lavinia", true); + File doc = WorkflowHelper.locateFile("org/olat/test/sandbox/4_within_subjects_vs_between_subjects_designs.zip"); + String remoteDoc = Context.getContext().provideFileRemotely(doc); + cpEditor.importPage("Introduction", remoteDoc); + } + } finally { + workflow.logout(); + } + } + + private void testCreateCourseWithTest() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + + CourseEditor courseEditor = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "bla"); + TestElementEditor test1 = (TestElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TEST, true, null); + test1.setTitle("TEST_1"); + test1.configureTestLayout(true, true, true, true, 10, true); + + + TestElementEditor test2 = (TestElementEditor)courseEditor.insertCourseElement(CourseEditor.CourseElemTypes.TEST, true, null); + test2.setTitle("TEST_2"); + test2.configureTestLayout(false, false, false, false, 0, false); + + courseEditor.publishCourse(); + CourseRun courseRun = courseEditor.closeToLRDetailedView().showCourseContent(); + + + workflow.logout(); + } + + public void testLearningGroup() throws Exception { + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(Context.getContext().getStandardAdminOlatLoginInfos()); + LRDetailedView lRDetailedView = workflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, "description").closeToLRDetailedView(); + GroupAdmin groupAdmin = lRDetailedView.showCourseContent().getGroupManagement().createLearningGroup(GROUP_NAME, "description", 0, false, false); + groupAdmin.setMemberDisplayOptions(null, true, null); + System.out.println("testLearningGroup"); + } + +} diff --git a/src/test/java/org/olat/test/sandbox/PreviewExternalPageTest.java b/src/test/java/org/olat/test/sandbox/PreviewExternalPageTest.java new file mode 100644 index 0000000000000000000000000000000000000000..149b307e672988ea344e9eea7880429bdc02f9a3 --- /dev/null +++ b/src/test/java/org/olat/test/sandbox/PreviewExternalPageTest.java @@ -0,0 +1,51 @@ +package org.olat.test.sandbox; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +/** + * + * Test issue OLAT-4597. + * Tries to reproduce a RS. + * <br/> + * <p> + * Test case: <br/> + * open course editor <br/> + * add course building block 'external page' <br/> + * Add an URL <br/> + * press preview button <br/> + * assert: there is NO RedScreen <br/> + * </p> + * + * @author alberto + * + */ +public class PreviewExternalPageTest extends BaseSeleneseTestCase { + private final String COURSE_NAME = "CourseName"+System.currentTimeMillis(); + private final String COURSE_DESCRIPTION = "CourseDescription"+System.currentTimeMillis(); + + public void testPreviewExternalPageTest() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + + OLATWorkflowHelper olatWorkflow = context.getOLATWorkflowHelper(context.getStandardAuthorOlatLoginInfos()); + + //open course editor + CourseEditor courseEditor = olatWorkflow.getLearningResources().createCourseAndStartEditing(COURSE_NAME, COURSE_DESCRIPTION); + + //add course building block 'external page' + + + //Add an URL + + //press preview button + + //=> assert: there is NO RedScreen NO RedScreen + + } +} diff --git a/src/test/java/org/olat/test/sandbox/package.html b/src/test/java/org/olat/test/sandbox/package.html new file mode 100644 index 0000000000000000000000000000000000000000..e9488da231caf9ed406c0231068060647ff705a0 --- /dev/null +++ b/src/test/java/org/olat/test/sandbox/package.html @@ -0,0 +1,12 @@ +<html> +<head> +</head> + +<body> + +This package contains tests waiting to be reviewed/implemented. +<br/> + + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/tutorial/cluster/clean/package.html b/src/test/java/org/olat/test/tutorial/cluster/clean/package.html new file mode 100644 index 0000000000000000000000000000000000000000..861e33f0bde4f4daab6270a955d8b2570e26016d --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/cluster/clean/package.html @@ -0,0 +1,14 @@ +<html> +<head> +</head> + +<body> + +Tests in this package are run against a clean cluster. +<p> +<i>Clean</i> means that the cluster is set up for each of the tests in this package +fresh from CVS with a fresh DB +<p> + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/tutorial/package.html b/src/test/java/org/olat/test/tutorial/package.html new file mode 100644 index 0000000000000000000000000000000000000000..80ffb6ee6d2d190d54659447c79150606c7ecbb9 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/package.html @@ -0,0 +1,12 @@ +<html> +<head> +</head> + +<body> + +This package should be removed. +<br/> + + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/tutorial/reg/ServerRestartTest.java b/src/test/java/org/olat/test/tutorial/reg/ServerRestartTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b251f25d49e7b7a9c321fa912a2641e9e75ef78c --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/reg/ServerRestartTest.java @@ -0,0 +1,37 @@ +package org.olat.test.tutorial.reg; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.SeleniumManager; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * This class tests 10x a singlevm server start and 10x a cluster server start + * . + * @author eglis + */ +public class ServerRestartTest extends BaseSeleneseTestCase { + + public void testRestarts() throws Exception { + for(int i=0; i<5; i++) { + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_TWO_NODE_CLUSTER); + Selenium s = context.createSeleniumAndLogin(); + s.close(); + s.stop(); + Context.tearDown(); + } + for(int i=0; i<5; i++) { + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); + Selenium s = context.createSeleniumAndLogin(); + s.close(); + s.stop(); + Context.tearDown(); + } + Context.setupContext(getFullName(), SetupType.SINGLE_VM); + } +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/junit/MacartneyBreakpointTest.java b/src/test/java/org/olat/test/tutorial/singlenode/junit/MacartneyBreakpointTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cfd688794f9ccf97060867219f37bfd8c916ef5b --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/junit/MacartneyBreakpointTest.java @@ -0,0 +1,100 @@ +package org.olat.test.tutorial.singlenode.junit; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.olat.testutils.codepoints.client.TemporaryPausedThread; + +public class MacartneyBreakpointTest extends BaseSeleneseTestCase { + + protected com.thoughtworks.selenium.Selenium selenium1; + protected com.thoughtworks.selenium.Selenium selenium2; + private CodepointClient codepointClient_; + + public void testMacartneyBreakpoint() throws Exception { + //if instance restart (SetupType.CLEAN_AND_RESTARTED_SINGLE_VM) is not implemented this test is not relevat! + if(true) { + return; + } + + + Context context = Context.setupContext(getFullName(), SetupType.CLEAN_AND_RESTARTED_SINGLE_VM); +// selenium1 = context.createSeleniumAndLogin(context.getStandardAdminOlatLoginInfos()); +// selenium2 = context.createSeleniumAndLogin(context.getStandardStudentOlatLoginInfos()); + + selenium1 = context.createSelenium(); + selenium2 = context.createSelenium(); + + // setup and get ready + selenium1.openWindow(context.getStandardAdminOlatLoginInfos().getFullOlatServerUrl(), "olat"); + selenium2.openWindow(context.getStandardStudentOlatLoginInfos().getFullOlatServerUrl(), "olat"); + System.out.println("olatLogin: waiting 5sec."); + Thread.sleep(5000); + System.out.println("olatLogin: selecting the olat window"); + selenium1.selectWindow("olat"); + selenium2.selectWindow("olat"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + System.out.println("title now: "+selenium1.getTitle()); + if (selenium1.getTitle().indexOf("Error")!=-1) { + System.out.println(selenium1.getBodyText()); + fail("Error encountered in selenium1"); + } + try { if ("OLAT - Online Learning And Training".equals(selenium1.getTitle())) break; } catch (Exception e) {} + Thread.sleep(1000); + } + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + System.out.println("title now: "+selenium2.getTitle()); + if (selenium2.getTitle().indexOf("Error")!=-1) { + System.out.println(selenium2.getBodyText()); + fail("Error encountered in selenium2"); + } + try { if ("OLAT - Online Learning And Training".equals(selenium2.getTitle())) break; } catch (Exception e) {} + Thread.sleep(1000); + } + selenium1.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT user name)", context.getStandardAdminOlatLoginInfos().getUsername()); + selenium1.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=OLAT password)", context.getStandardAdminOlatLoginInfos().getPassword()); + + selenium2.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT user name)", context.getStandardStudentOlatLoginInfos().getUsername()); + selenium2.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=OLAT password)", context.getStandardStudentOlatLoginInfos().getPassword()); + + + codepointClient_ = context.createCodepointClient(1); + codepointClient_.setAllHitCounts(0); + CodepointRef beforeSyncCp = codepointClient_.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-before-sync.org.olat.portal.macartney.MacartneyPortletRunController.<init>"); + beforeSyncCp.setHitCount(0); + beforeSyncCp.enableBreakpoint(); + + CodepointRef inSyncCp = codepointClient_.getCodepoint("org.olat.commons.coordinate.cluster.ClusterSyncer.doInSync-in-sync.org.olat.portal.macartney.MacartneyPortletRunController.<init>"); + inSyncCp.setHitCount(0); + + //MacartneyPortletRunController + + selenium1.click("ui=dmz::login()"); + selenium2.click("ui=dmz::login()"); + + Thread.sleep(10000); + inSyncCp.assertHitCount(0); + beforeSyncCp.assertHitCount(2); + + TemporaryPausedThread[] threads = beforeSyncCp.getPausedThreads(); + assertNotNull(threads); + assertEquals(2, threads.length); + + // continue the first + threads[0].continueThread(); + Thread.sleep(500); + + threads = beforeSyncCp.getPausedThreads(); + assertNotNull(threads); + assertEquals(1, threads.length); + inSyncCp.assertHitCount(1); + + //selenium1.waitForPageToLoad("30000"); + //assertEquals("OLAT-Home", selenium.getTitle()); + } + +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/testng/CourseOpenCloseTest.java b/src/test/java/org/olat/test/tutorial/singlenode/testng/CourseOpenCloseTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4d1a01a4453f224efa6558898e1b94741ebfce90 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/testng/CourseOpenCloseTest.java @@ -0,0 +1,29 @@ +package org.olat.test.tutorial.singlenode.testng; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +@Test(groups = {"sequential"}, enabled=true ) +public class CourseOpenCloseTest extends BaseSeleneseTestCase { + + @Test + public void testCourseOpenClose() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSeleniumAndLogin(); + + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium.click("ui=learningResources::content_searchForm_search()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_showContent()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=tabs::closeCourse(nameOfCourse=Demo course wiki)"); + } +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/testng/CoursePublishTest.java b/src/test/java/org/olat/test/tutorial/singlenode/testng/CoursePublishTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ff030ae6667f6e70c05704c6918279d54919e6db --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/testng/CoursePublishTest.java @@ -0,0 +1,59 @@ +package org.olat.test.tutorial.singlenode.testng; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +@Test(groups = {"sequential"}) +public class CoursePublishTest extends BaseSeleneseTestCase { + + @Test + public void testCoursePublish(String olatUrl) throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSeleniumAndLogin(); + + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::content_searchForm_titleField()", "Demo course wiki"); + selenium.click("ui=learningResources::content_searchForm_search()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_clickCourseEntry(nameOfCourse=Demo course wiki)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_showContent()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=courseEditor::content_TitleDescription_shortTitle()", "mod"); + selenium.click("ui=courseEditor::content_TitleDescription_save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent("Publishing")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + assertTrue(selenium.isTextPresent("No problems found")); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + //assertTrue(selenium.isTextPresent("Do you really want to publish this course?")); + assertTrue(selenium.isTextPresent("Please confirm that you really want to publish the following course elements")); + selenium.click("ui=courseEditor::publishDialog_finish()"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent("Selected modifications published successfully")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium.click("ui=tabs::closeCourse(nameOfCourse=Demo course wiki)"); + } + +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/testng/CreateUserTest.java b/src/test/java/org/olat/test/tutorial/singlenode/testng/CreateUserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..16dc086f7ad175056aa9251fca104a3e5aadcd24 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/testng/CreateUserTest.java @@ -0,0 +1,28 @@ +package org.olat.test.tutorial.singlenode.testng; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +@Test(groups = {"sequential"}) +public class CreateUserTest extends BaseSeleneseTestCase { + + @Test + public void testCoursePublish() throws Exception { + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSelenium(); + + OlatLoginInfos loginInfos = context.getStandardAdminOlatLoginInfos(); + OlatLoginInfos newLoginInfos = + WorkflowHelper.createUserIfNotExists(loginInfos, "newuser3", "newpassword2", true, true, false, true, false); + + OlatLoginHelper.olatLogin(selenium, newLoginInfos); + assertEquals("OLAT - Home", selenium.getTitle()); + OlatLoginHelper.olatLogout(selenium); + } + +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialJUnitTest.java b/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialJUnitTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d907435b48aa2e908a5f64c680ec62e8cf811a4e --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialJUnitTest.java @@ -0,0 +1,50 @@ +package org.olat.test.tutorial.singlenode.testng; + +import junit.framework.TestCase; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +@Test(groups = {"sequential"} ) +public class SimpleTutorialJUnitTest extends TestCase { + + @BeforeClass + public void beforeClass() { + System.out.println("SimpleTutorialTest.beforeClass"); + } + + @BeforeTest + public void beforeTest() { + System.out.println("SimpleTutorialTest.beforeTest"); + } + + @BeforeMethod + public void beforeMethod() { + System.out.println("SimpleTutorialTest.beforeMethod"); + } + + @Test + public void theSimpleTutorialJUnitTest() { + System.out.println("SimpleTutorialTest.theTest"); + } + + @AfterMethod + public void afterMethod() { + System.out.println("SimpleTutorialTest.afterMethod"); + } + + @AfterTest + public void afterTest() { + System.out.println("SimpleTutorialTest.afterTest"); + } + + @AfterClass + public void afterClass() { + System.out.println("SimpleTutorialTest.afterClass"); + } +} diff --git a/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialTest.java b/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f87acc0a533b2c9e3fc0c06843627103199110d9 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/singlenode/testng/SimpleTutorialTest.java @@ -0,0 +1,48 @@ +package org.olat.test.tutorial.singlenode.testng; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +@Test(groups = {"sequential"} ) +public class SimpleTutorialTest { + + @BeforeClass + public void beforeClass() { + System.out.println("SimpleTutorialTest.beforeClass"); + } + + @BeforeTest + public void beforeTest() { + System.out.println("SimpleTutorialTest.beforeTest"); + } + + @BeforeMethod + public void beforeMethod() { + System.out.println("SimpleTutorialTest.beforeMethod"); + } + + @Test + public void theSimpleTutorialTest() { + System.out.println("SimpleTutorialTest.theTest"); + } + + @AfterMethod + public void afterMethod() { + System.out.println("SimpleTutorialTest.afterMethod"); + } + + @AfterTest + public void afterTest() { + System.out.println("SimpleTutorialTest.afterTest"); + } + + @AfterClass + public void afterClass() { + System.out.println("SimpleTutorialTest.afterClass"); + } +} diff --git a/src/test/java/org/olat/test/tutorial/testng/TIPS_AND_TRICKS.txt b/src/test/java/org/olat/test/tutorial/testng/TIPS_AND_TRICKS.txt new file mode 100644 index 0000000000000000000000000000000000000000..a2ab9db14a047e71a4f6a6ee78a112fc5862ddf7 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/testng/TIPS_AND_TRICKS.txt @@ -0,0 +1,41 @@ +Assorted Tips and Tricks for TestNG: +==================================== + + * If you specify a method as @Test in the following way: + + @Test + public void xy() {} + + and don't specify the class as a whole as @Test - then only + that method is invoked - no other @BeforeXXX or @AfterXXX + + Therefore make sure to mark the whole class as @Test when you + have @BeforeXXX or @AfterXXX in that class! + + * Alternative, if you have a class which is not defined as @Test + (this can include a base class for example where it is not + feasible to mark it as @Test - esp you dont want to add + any group to base classes thus the @Test wouldnt even have + an effect): + + you can always mark a method with alwaysRun: + + @AfterMethod(alwaysRun=true) + public void tearDown() {} + + This makes sure that this method is run, when a test method + in this or a subclass is run + + * Running a single class and a group of classes can have sideeffects + on @BeforeXXX/@AfterXXX: + + When explicitly running a class as a TestNG Test (in Eclipse), + then all @BeforeXXX/@AfterXXX methods are executed, irrespective + of the alwaysRun - that is what you would normally expect. + + BUT WATCH OUT! When you run the same test as part of a group + or package, then @BeforeXXX/@AfterXXX is ONLY RUN when + the whole class is marked as @Test: + + @Test + public class MyTestClass { } \ No newline at end of file diff --git a/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassA.java b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassA.java new file mode 100644 index 0000000000000000000000000000000000000000..b32e7f27936dfe11ae6d6eb486ab2220b9894096 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassA.java @@ -0,0 +1,56 @@ +package org.olat.test.tutorial.testng.dependencies; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +@Test(groups = {"dependencies"} ) +public class ClassA { + + @BeforeSuite + void beforeSuite() { + System.out.println("Before Suite"); + } + + @AfterSuite + void afterSuite() { + System.out.println("After Suite"); + } + + @BeforeTest + void beforeTest() { + System.out.println("Before Test"); + } + + @AfterTest + void afterTest() { + System.out.println("After Test"); + } + + @BeforeClass + void beforeClass() { + System.out.println("Before Class"); + } + + @AfterClass + void afterClass() { + System.out.println("After Class"); + } + + @BeforeMethod + void beforeMethod() { + System.out.println("Before Method"); + } + + @AfterMethod + void afterMethod() { + System.out.println("After Method"); + } + +} diff --git a/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassB.java b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassB.java new file mode 100644 index 0000000000000000000000000000000000000000..313d2ddb2c3624787b25daf6cfc30156bfda9d4d --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassB.java @@ -0,0 +1,11 @@ +package org.olat.test.tutorial.testng.dependencies; + +import org.testng.annotations.Test; + +public class ClassB { + + @Test(groups = {"dependencies"} ) + public void methodB() { + System.out.println("MethodB"); + } +} diff --git a/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassC.java b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassC.java new file mode 100644 index 0000000000000000000000000000000000000000..a4dbc91d0751d1a9e04f6659e453d9db3f371553 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/testng/dependencies/ClassC.java @@ -0,0 +1,11 @@ +package org.olat.test.tutorial.testng.dependencies; + +import org.testng.annotations.Test; + +public class ClassC { + + @Test(groups = {"dependencies"} ) + public void methodC() { + System.out.println("methodC"); + } +} diff --git a/src/test/java/org/olat/test/tutorial/testng/parallel/TestParallel.java b/src/test/java/org/olat/test/tutorial/testng/parallel/TestParallel.java new file mode 100644 index 0000000000000000000000000000000000000000..75886b266d068e6a4c1300f0ab26f0e46a011536 --- /dev/null +++ b/src/test/java/org/olat/test/tutorial/testng/parallel/TestParallel.java @@ -0,0 +1,37 @@ +package org.olat.test.tutorial.testng.parallel; + +import junit.framework.TestCase; + +import org.testng.annotations.Test; + +public class TestParallel extends TestCase { + + @Test + public void testMethod1() throws Exception { + System.out.println("method1..."); + Thread.sleep(5000); + System.out.println("end method1."); + } + + @Test + public void testMethod2() throws Exception { + System.out.println("method2..."); + Thread.sleep(5000); + System.out.println("end method2."); + } + + @Test + public void testMethod3() throws Exception { + System.out.println("method3..."); + Thread.sleep(5000); + System.out.println("end method3."); + } + + @Test + public void testMethod4() throws Exception { + System.out.println("method4..."); + Thread.sleep(5000); + System.out.println("end method4."); + } + +} diff --git a/src/test/java/org/olat/test/util/MessageOrderingTest.java b/src/test/java/org/olat/test/util/MessageOrderingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f82db9fecb7ff67df19d86f98c9cc8a2aab03725 --- /dev/null +++ b/src/test/java/org/olat/test/util/MessageOrderingTest.java @@ -0,0 +1,64 @@ +package org.olat.test.util; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.command.ActiveMQQueue; + +public class MessageOrderingTest implements MessageListener { + + private int counter_ = 0; + + public static void main(String[] args) throws Exception { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); + connectionFactory.setBrokerURL("tcp://localhost:61616"); + + Connection connection = connectionFactory.createQueueConnection(); + Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Destination destination = new ActiveMQQueue("/atestqueue"); + + MessageProducer producer = session1.createProducer(destination); + + MessageConsumer consumer = session2.createConsumer(destination); + + consumer.setMessageListener(new MessageOrderingTest()); + connection.start(); + + for(int i=0; i<10000; i++) { + MapMessage message = session1.createMapMessage(); + message.setInt("Counter", i); + producer.send(message); + System.out.println("Sent counter="+i); + } + } + + public void onMessage(Message arg0) { + try{ + if (!(arg0 instanceof MapMessage)) { + new Exception("Wrong message type: "+arg0).printStackTrace(System.out); + System.exit(1); + } + MapMessage message = (MapMessage)arg0; + int receivedCounter = message.getInt("Counter"); + System.out.println("Received counter="+receivedCounter); + if (receivedCounter!=counter_) { + new Exception("Out of order, expected "+counter_+", but got "+receivedCounter).printStackTrace(System.out); + System.exit(1); + } + counter_++; + } catch(JMSException e) { + e.printStackTrace(System.out); + System.exit(1); + } + } +} diff --git a/src/test/java/org/olat/test/util/selenium/BaseSeleneseTestCase.java b/src/test/java/org/olat/test/util/selenium/BaseSeleneseTestCase.java new file mode 100644 index 0000000000000000000000000000000000000000..1f62d2c164051019148d245a33c0a878b535d82d --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/BaseSeleneseTestCase.java @@ -0,0 +1,81 @@ +package org.olat.test.util.selenium; + +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.AfterMethod; + +import com.thoughtworks.selenium.SeleneseTestCase; + +/** + * Base class for running Selenium tests in OLAT - all test cases + * should extend this class.</P> + * The environment of a test is defined over the a Context or derived class of it, and the corresponding spring context configuration. + * + * @author Stefan + */ +public class BaseSeleneseTestCase extends SeleneseTestCase { + + public String getFullName() { + return getClass().getCanonicalName()+"."+getName(); + } + + @Override + public void setUp() throws Exception { + // don't do anything by default - including not calling super.setUp() + } + + /** + * Hooks for subclasses who wanted to overwrite tearDown() - but + * the BaseSeleneseTestCase requires tearDown() to be called in + * any case - thus enforces this pattern of + * try{ + * doTearDown(); + * } finally { + * // do the framework.tearDown stuff anyway + * } + * @throws Exception + */ + public void doTearDown() throws Exception { + // nothing by default + } + + @Override + @AfterMethod(alwaysRun=true) + public final void tearDown() throws Exception { + try{ + checkForVerificationErrors(); + doTearDown(); + } finally { + Context.tearDown(); + } + + // don't call super.tearDown() by default - since we instantiate multiple selenium's here + // and the default 'selenium' instance variable might not be initialized - thus + // a NullPointerException will occur in this case when we call super.tearDown() here. + } + + @Override + protected void runTest() throws Throwable { + try{ + super.runTest(); + + + } catch(Throwable th) { + // OLAT-3653: in case of a failure, try to find out if it is a KnownIssueException somewhere in the + // olat.log - and if so, don't report it as the original failure but as a known issue so we immediately + // know from the test result that it is a known issue + if (!Context.maskTestFailureOrError(th)) { + throw th; + } + } + cleanUpAfterRun(); + } + + /** + * Clean up code to perform after the successful run. + * + */ + protected void cleanUpAfterRun() { + // nothing by default + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/OlatLoginHelper.java b/src/test/java/org/olat/test/util/selenium/OlatLoginHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..0b6068b5b0359708d54048bc2bd3afc42cb5ddf0 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/OlatLoginHelper.java @@ -0,0 +1,281 @@ +package org.olat.test.util.selenium; + +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * Provides login, logout functionality. + * + * @author stefan + * + */ +public class OlatLoginHelper { + + /** + * Logout is anywhere available in OLAT. + * @param selenium + */ + public static void olatLogout(Selenium selenium) { + selenium.click("ui=tabs::logOut"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @param selenium + * @param loginInfos + */ + public static void olatLogin(Selenium selenium, OlatLoginInfos loginInfos) { + String username = loginInfos.getUsername(); + String password = loginInfos.getPassword(); + String language = loginInfos.getLanguage(); + boolean success = false; + try { + for (int second = 0;; second++) { + if (second >= 120) + fail("timeout. Could not get to see 'OLAT - Online Learning And Training'... is OLAT down?"); + System.out.println("title now: " + selenium.getTitle()); + try { + if ("OLAT - Online Learning And Training".equals(selenium + .getTitle())) + break; + } catch (Exception e) { + } + sleep(500); + } + if (selenium.isTextPresent("OLAT-Benutzername") + && !language.equals("Deutsch")) { + // then we have to switch to english... + selenium.select("//select[contains(@name, 'language_SELBOX')]", "label=" + language); + for (int second = 0;; second++) { + if (second >= 120) + fail("timeout. Could not switch to English in DMZ!"); + try { + if (selenium.isTextPresent("OLAT user name")) + break; + } catch (Exception e) { + } + sleep(500); + } + } + assertEquals("OLAT - Online Learning And Training", selenium + .getTitle()); + login: while (true) { + System.out.println("logging in to " + selenium.getLocation() + + " as " + username); + + inputUserNameAndPassword(selenium, username, password); + + //sleep(5000); + if(selenium.isTextPresent("Terms of use") ) { + //accept disclaimer + selenium.click("ui=dmz::disclaimerCheckbox()"); + selenium.click("ui=dmz::acceptDisclaimer(acceptLabel=Accept)"); + selenium.waitForPageToLoad("30000"); + System.out.println("accept disclaimer - EN"); + } else if(selenium.isTextPresent("Nutzungsbedingungen")) { + selenium.click("ui=dmz::disclaimerCheckbox()"); + selenium.click("ui=dmz::acceptDisclaimer(acceptLabel=Akzeptieren)"); + selenium.waitForPageToLoad("30000"); + System.out.println("accept disclaimer - DE"); + } + + System.out.println("waiting for home page to open..."); + for (int second = 0;; second++) { + if (second >= 120) + fail("timeout. Could not login with username="+username+", password="+password); + System.out.println("fetching title..."); + System.out.println("title now: " + selenium.getTitle()); + try { + if ("OLAT - Home".equals(selenium.getTitle())) + break; + } catch (Exception e) { + } + sleep(500); + } + System.out.println("Great, Home opened!"); + + if (selenium.isElementPresent("ui=home::menu_settings()") + && language.equals("English")) { + // language is correct + break; + } + if (selenium.isElementPresent("ui=home::menu_einstellungen()") + && language.equals("Deutsch")) { + // language is correct + break; + } + + if (!selenium.isElementPresent("ui=home::menu_einstellungen()") + && !selenium + .isElementPresent("ui=home::menu_settings()")) { + fail("only supporting default language German or English for switching to another language at the moment"); + } + + if (selenium.isElementPresent("ui=home::menu_einstellungen()")) { + // then we're in german, lets switch to english + System.out + .println("We're in german, lets set the correct language"); + selenium.click("ui=home::menu_einstellungen()"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=home::content_einstellungen_tabs_system()"); + selenium.waitForPageToLoad("60000"); + selenium.select( + "ui=home::content_einstellungen_system_sprache()", + "label=" + language); + selenium + .click("ui=home::content_einstellungen_system_speichern()"); + selenium.waitForPageToLoad("30000"); + System.out.println("HTMLSOURCE: " + + selenium.getHtmlSource()); + sleep(600); + if (selenium.isElementPresent("ui=tabs::logOut()")) { + System.out.println("logOut present!"); + } else { + for(int k=0; k<30; k++) { + while(!selenium.isElementPresent("ui=tabs::logOut()")) { + System.out.println("logOut not present!"); + sleep(500); + } + } + if (!selenium.isElementPresent("ui=tabs::logOut()")) { + System.out.println("logOut not present!"); + } + } + selenium.click("ui=tabs::logOut()"); + } else { + // then we're in german, lets switch to english + System.out + .println("We're in english, lets set the correct language"); + selenium.click("ui=home::menu_settings()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=home::content_settings_tabs_system()"); + selenium.waitForPageToLoad("30000"); + selenium + .select( + "ui=home::content_settings_system_general_language()", + "label=" + language); + selenium + .click("ui=home::content_settings_system_general_save()"); + selenium.waitForPageToLoad("30000"); + System.out.println("HTMLSOURCE: " + + selenium.getHtmlSource()); + sleep(600); + if (selenium.isElementPresent("ui=tabs::logOut()")) { + System.out.println("logOut present!"); + } else { + System.out.println("logOut not present!"); + } + selenium.click("ui=tabs::logOut()"); + } + + System.out.println("waiting for logout to be done"); + selenium.waitForPageToLoad("30000"); + for (int second = 0;; second++) { + if (second >= 120) + fail("timeout. Could not go back to DMZ to see 'OLAT - Online Learning And Training', did the logOut fail ?"); + System.out.println("title now: " + selenium.getTitle()); + try { + if ("OLAT - Online Learning And Training" + .equals(selenium.getTitle())) + break; + } catch (Exception e) { + } + sleep(500); + } + continue login; + } + System.out.println("login of user " + username + " to url " + + selenium.getLocation() + " successful"); + success = true; + } finally { + System.out.println("OLATLOGIN FINALLY. success="+success); + if (!success) { + System.out.println("Body: "+selenium.getBodyText()); + } + } + } + + /** + * Enter username and password, and press login, no matter whether the login form is in English or German. + * @param selenium + * @param username + * @param password + */ + public static void inputUserNameAndPassword(Selenium selenium, String username, String password) { + //if shib login, go to olat login + if(selenium.isElementPresent("ui=dmz::wayf()")) { + //switch to olat login + if(selenium.isElementPresent("ui=commons::anyLink(linkText=Weiter)")) { + selenium.click("ui=commons::anyLink(linkText=Weiter)"); + selenium.waitForPageToLoad("60000"); + } else if(selenium.isElementPresent("ui=commons::anyLink(linkText=Next)")) { + selenium.click("ui=commons::anyLink(linkText=Next)"); + selenium.waitForPageToLoad("60000"); + } + } + //assuming that we are on the olat login page... + if(selenium.isElementPresent("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT-Benutzername)")) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT-Benutzername)", username); + sleep(5000); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=OLAT-Passwort)", password); + sleep(5000); + } else if(selenium.isElementPresent("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT user name)")) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=OLAT user name)", username); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=OLAT password)", password); + } + selenium.click("ui=dmz::login()"); + selenium.waitForPageToLoad("30000"); + } + + private static void sleep(int time) { + while(true) { + try { + Thread.sleep(time); + return; + } catch (InterruptedException e) { + // do it again + } + } + } + + private static void assertEquals(String expected, String actual) { + if (expected==null && actual==null) { + return; + } else if (expected==null || actual==null) { + throw new AssertionError("expected "+expected+" but got "+actual); + } else if (!expected.equals(actual)) { + throw new AssertionError("expected "+expected+" but got "+actual); + } + } + + static void fail(String msg) { + throw new AssertionError("failure: "+msg); + } + + /** + * Try to login but gets an error message. + * @param nodeId + * @param username + * @param password + * @return Returns true, if it gets an error msg at login. + */ + public static boolean loginExpectingError(int nodeId, String username, String password) throws Exception{ + Selenium selenium = Context.getContext().createSelenium(Context.getContext().getOlatLoginInfo(nodeId, username, password)); + assertEquals("OLAT - Online Learning And Training", selenium.getTitle()); + System.out.println("logging in to " + selenium.getLocation() + " as " + username); + inputUserNameAndPassword(selenium, username, password); + + boolean cannotLogin = SeleniumHelper.isTextPresent(selenium, "OLAT user name or password invalid", 20); //English error message + cannotLogin |= SeleniumHelper.isTextPresent(selenium, "Fehler", 20); // German error message + /*if(!cannotLogin) { + fail("Expected to get an error message while login!"); + }*/ + selenium.click("ui=dmz::loginErrorOK()"); + return cannotLogin; + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/PageLoadWait.java b/src/test/java/org/olat/test/util/selenium/PageLoadWait.java new file mode 100644 index 0000000000000000000000000000000000000000..1452396032043b75764c62c5491b03c932508087 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/PageLoadWait.java @@ -0,0 +1,67 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium; + + +/** + * Defines different page load waiting times in ms and allows nowait time. + * The facility "Not waiting" for page load was introduced in conjunction with codepoints. See the following example + * <pre> + //trigger "Activation Content" which in turn loads each of its children for displaying the Previews -> Changed behavior of test! + StructureElement selectActivation = courseRun.selectAnyButGetToRoot("Activation Interaction", PageLoadWait.NO_WAIT); + selenium = selectActivation.getSelenium(); + + // ASSERTION check if codepoint reached, if yes continue + beforeSyncCp_A.assertBreakpointReached(1, 10000); + System.out.println("beforeSyncCp_A.assertBreakpointReached"); + TemporaryPausedThread[] threadsA = beforeSyncCp_A.getPausedThreads(); + threadsA[0].continueThread(); + + doInSyncCp_A.assertBreakpointReached(1, 10000); + System.out.println("doInSyncCp_A.assertBreakpointReached"); + threadsA = doInSyncCp_A.getPausedThreads(); //overwrite threadsA + threadsA[0].continueThread(); + + // activate actual "Forum" content for proceeding + selenium.waitForPageToLoad("30000");//wait for previous NO_WAITED Action + courseRun.selectForum(CourseEditor.FORUM_COURSE_ELEM_TITLE); + </pre> + * <P> + * Initial Date: Apr 29, 2011 <br> + * + * @author patrick + */ +public enum PageLoadWait { + + LONG("60000"), DEFAULT("30000"), SHORT("5000"), NO_WAIT("0"); + + //ms are specified via String to Selenium + private String ms; + + PageLoadWait(String msValue) { + this.ms = msValue; + } + + public String getMs() { + return ms; + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/SeleniumHelper.java b/src/test/java/org/olat/test/util/selenium/SeleniumHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..bddc2ec8b875398d3201583adfc9327132bfc1cc --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/SeleniumHelper.java @@ -0,0 +1,77 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium; + +import com.thoughtworks.selenium.Selenium; +import junit.framework.Assert; + +/** + * @author Lavinia Dumitrescu + * + */ +public class SeleniumHelper extends Assert { + + /** + * If timeout exceeded fails. + * @param selenium + * @param text + * @return Returns true if text was present. + * @throws Exception + */ + public static boolean waitUntilTextPresent(Selenium selenium, String text, int timeoutSec) throws Exception { + for (int second = 0;; second++) { + if (second >= timeoutSec) fail("timeout"); + try { + if (selenium.isTextPresent(text)) + return true; + } catch (Exception e) {} + Thread.sleep(1000); + } + } + + /** + * Checks if text shows up in the first timeoutSec. + * @param selenium + * @param text + * @param timeoutSec + * @return Return true if the test was present, else false. + */ + public static boolean isTextPresent(Selenium selenium, String text, int timeoutSec) throws Exception { + for (int second = 0; second <= timeoutSec; second++) { + try { + if (selenium.isTextPresent(text)) + return true; + } catch (Exception e) {} + Thread.sleep(1000); + } + return false; + } + + public static void safeWait(long milliseconds){ + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/src/test/java/org/olat/test/util/selenium/SeleniumManager.java b/src/test/java/org/olat/test/util/selenium/SeleniumManager.java new file mode 100644 index 0000000000000000000000000000000000000000..81a5c8c3f6c2c633033997fd308d17db745a2260 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/SeleniumManager.java @@ -0,0 +1,218 @@ +package org.olat.test.util.selenium; + +import java.io.OutputStreamWriter; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.AssertionFailedError; + +import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import org.olat.test.util.selenium.log.LoggingSeleniumWrapper; +import org.olat.test.util.setup.OlatLoginInfos; + +import com.thoughtworks.selenium.DefaultSelenium; +import com.thoughtworks.selenium.Selenium; +import com.thoughtworks.selenium.SeleniumException; + +/** + * Creates and manages the selenium instances. + * + * @author stefan + * + */ +public class SeleniumManager { + + private static final Logger seleniumLogger_; + + static { + seleniumLogger_ = Logger.getLogger("Selenium"); + seleniumLogger_.setLevel(Level.INFO); + ConsoleAppender appender = new ConsoleAppender(); + appender.setLayout(new PatternLayout("%d [%t] %-5p %c{1} %x -_._- %m%n")); + appender.setWriter(new OutputStreamWriter(System.out)); + seleniumLogger_.addAppender(appender); + } + + private final String nameOfTest_; + + private List<Selenium> seleniums_ = new LinkedList<Selenium>(); + + /** + * + * @param nameOfTest + */ + public SeleniumManager(String nameOfTest) { + nameOfTest_ = nameOfTest; + } + + /** + * Creates a new DefaultSelenium, wraps it into a LoggingSeleniumWrapper, and opens Window. <br/> + * It adds the newly created selenium instance to the seleniums list. + * + * @param loginInfos + * @return + */ + public Selenium createSelenium(OlatLoginInfos loginInfos) { + String hostname = loginInfos.getSeleniumHostname(); + String browserId = loginInfos.getSeleniumBrowserId(); + String initialBrowserUrl = loginInfos.getFullOlatServerUrl(); + int port = getDefaultPort(); + System.out.println("connecting to "+hostname+" port "+port+"..." + " browserId: " + browserId + " initialBrowserUrl: " + initialBrowserUrl); + Selenium selenium = null; + + for(int i=1; i<6; i++) { + try{ + selenium = new DefaultSelenium(hostname, port, browserId, initialBrowserUrl); + System.out.println("createSelenium - DefaultSelenium created"); + + selenium.start(); + //Thread.sleep(100000); + System.out.println("createSelenium - DefaultSelenium started"); + // the next line can fail at times + selenium.setContext(this.getClass().getSimpleName() + "." + nameOfTest_); + //selenium.setBrowserLogLevel("debug"); + + System.out.println("connected."); + + selenium = new LoggingSeleniumWrapper(selenium, seleniumLogger_); + + System.out.println("createSelenium: launching browser (url="+loginInfos.getFullOlatServerUrl()+")"); + + // the next line can fail at times + selenium.openWindow(loginInfos.getFullOlatServerUrl(), "olat"); + + System.out.println("createSelenium: success so far."); + // success + break; + } catch (SeleniumException se) { + selenium = null; + System.out.println("createSelenium: browser creation failed...:"); + se.printStackTrace(System.out); + System.out.println("createSelenium: retrying in "+i+"*5 sec..."); + try { + Thread.sleep(i*5000); + } catch (InterruptedException e) { + e.printStackTrace(System.out); + } + System.out.println("createSelenium: ok, retrying now..."); + } catch (Exception ex) { + System.out.println("createSelenium: browser creation failed...:"); + ex.printStackTrace(System.out); + System.out.println("createSelenium: retrying in "+i+"*5 sec..."); + } + } + + if (selenium==null) { + System.out.println("createSelenium: COULD NOT CREATE A BROWSER, EVEN THOUGH I TRIED 5 TIMES WITH 5 SEC DELAYS. GIVING UP HERE."); + throw new AssertionFailedError("Could not create browser even though I tried 5 times with 5 sec delays, giving up"); + } + System.out.println("createSelenium: waiting 5sec."); + selenium.waitForPopUp("olat", "30000"); + System.out.println("createSelenium: selecting the olat window"); + selenium.selectWindow("olat"); + if (selenium.isTextPresent("OLAT-Benutzername")) { + // then we have to switch to english... + selenium.select("//select[contains(@name, 'language_SELBOX')]", "label=English"); + for (int second = 0;; second++) { + if (second >= 120) throw new AssertionError("timeout while checking for language change to English to occur"); + try { if (selenium.isTextPresent("OLAT user name")) break; } catch (Exception e) {} + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // ignore + } + } + } + + seleniums_.add(selenium); + return selenium; + } + + /** + * Closes all selenium instances found in the seleniums list. + */ + public void closeSeleniums() { + System.out.println("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*"); + System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-"); + System.out.println("* Getting body texts of all selenium browsers: *"); + int i = 0; + for (Iterator<Selenium> it = seleniums_.iterator(); it.hasNext();) { + Selenium s = (Selenium) it.next(); + System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-"); + System.out.println("* Selenium["+(i++)+","+s+"].getBodyText(): *"); + System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-"); + try{ + System.out.println(s.getBodyText()); + } catch(Exception e) { + //e.printStackTrace(System.out); + System.out.println("Couldn't fetch body of Selenium["+(i-1)+"]: "+e); + } + /*try{ + String filename = System.currentTimeMillis()+".png"; + System.out.println("Capturing screenshot into: "+filename); + s.captureEntirePageScreenshot(filename); + } catch(Exception e) { + System.out.println("Couldn't capture screenshot :( - "+e); + }*/ + } + System.out.println("* Done with getting body of all seleniums *"); + System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-"); + System.out.println("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*"); + System.out.println("Killing the selenium servers..."); + for (Iterator<Selenium> it = seleniums_.iterator(); it.hasNext();) { + Selenium s = it.next(); + doClose(s); + } + } + + public boolean anySeleniumBrowserHasKnownIssue3857() { + for (Iterator<Selenium> it = seleniums_.iterator(); it.hasNext();) { + Selenium s = (Selenium) it.next(); + try{ + final String body = s.getBodyText(); + if (body.contains("Please do not use the `Reload` or `Back` button of your browser.")) { + return true; + } + } catch(Exception e) { + // ignore + } + } + return false; + } + + private static void doClose(Selenium selenium) { + try{ + selenium.close(); + } catch(Exception e) { + e.printStackTrace(); + } finally { + try{ + selenium.stop(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + } + + /** + * Default port is 4444. + * @return + */ + public static int getDefaultPort() { + try { + Class c = Class.forName("org.openqa.selenium1.server.SeleniumServer"); + Method getDefaultPort = c.getMethod("getDefaultPort", new Class[0]); + Integer portNumber = (Integer)getDefaultPort.invoke(null, new Object[0]); + return portNumber.intValue(); + } catch (Exception e) { + return 4444; + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/log/Log4jSocketServer.java b/src/test/java/org/olat/test/util/selenium/log/Log4jSocketServer.java new file mode 100644 index 0000000000000000000000000000000000000000..e5bb6ecaa9a7fed00e9a2d87686e7a547c147cb4 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/log/Log4jSocketServer.java @@ -0,0 +1,140 @@ +package org.olat.test.util.selenium.log; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.apache.log4j.LogManager; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.net.SocketNode; + +public class Log4jSocketServer { + + static { + System.out.println("=============================="); + System.out.println("Log4jSocketServer<static-init>"); + System.out.println("=============================="); + } + + static int port = 18081; + private static Thread thread_; + private static ServerSocket serverSocket_; + private static Object syncObj_ = new Object(); + private static boolean stop_ = false; + + /** + * + * @param log4JConfigFilename + */ + public static void setLog4JConfigFilename(String log4JConfigFilename) { + System.out.println("Log4jSocketServer - setLog4JConfigFilename: " + log4JConfigFilename); + PropertyConfigurator.configure(log4JConfigFilename); + } + + public static boolean isStarted() { + return thread_!=null; + } + + /** + * Call setLog4JConfigFilename before!!! + */ + public static void start() { + if (thread_!=null) { + System.out.println("========================="); + System.out.println("Log4jSocketServer.start(): already active"); + System.out.println("========================"); + stop(); +// throw new IllegalArgumentException("Log4jSocketServer already started (make sure to call super.tearDown() in your tests if you overwrite tearDown())"); + } + System.out.println("========================="); + System.out.println("Log4jSocketServer.start()"); + System.out.println("========================="); + stop_ = false; + serverSocket_ = null; + thread_ = new Thread(new Runnable() { + + private List<Socket> socketNodeSockets_ = new LinkedList<Socket>(); + + public void run() { + try { + System.out.println("[Log4jSocketServer] Listening on port " + port); + //System.setProperty("log4j.debug", "true"); + serverSocket_ = new ServerSocket(port); + while (true) { + synchronized (syncObj_) { + if (stop_) { + return; + } + } + System.out.println("[Log4jSocketServer] Waiting to accept a new client."); + Socket socket = serverSocket_.accept(); + System.out.println("[Log4jSocketServer] Connected to client at " + + socket.getInetAddress()); + System.out.println("[Log4jSocketServer] Starting new socket node."); + SocketNode socketNode = new SocketNode(socket, LogManager + .getLoggerRepository()); + Thread thread = new Thread(socketNode, "SimpleSocketServer-" + + port); + thread.setDaemon(true); + socketNodeSockets_.add(socket); + thread.start(); + } + } catch (Exception e) { + synchronized (syncObj_) { + if (stop_) { + return; + } + } + e.printStackTrace(); + } finally { + System.out.println("[Log4jSocketServer] Cleaning up Log4jSocketServer mess... ("+socketNodeSockets_.size()+" sockets)"); + thread_ = null; + for (Iterator<Socket> it = socketNodeSockets_.iterator(); it + .hasNext();) { + Socket socket = it.next(); + try { + System.out.println("[Log4jSocketServer] Shutting down socket "+socket+"..."); + socket.shutdownInput(); + socket.shutdownOutput(); + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + }); + thread_.setDaemon(true); + thread_.start(); + try { + Thread.sleep(300); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public static void stop() { + if (serverSocket_ == null) { + System.out.println("========================"); + System.out.println("Log4jSocketServer.stop(): not active"); + System.out.println("========================"); + return; + } + System.out.println("========================"); + System.out.println("Log4jSocketServer.stop()"); + System.out.println("========================"); + synchronized(syncObj_) { + stop_ = true; + } + try { + serverSocket_.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/log/LoggingSeleniumWrapper.java b/src/test/java/org/olat/test/util/selenium/log/LoggingSeleniumWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..673a04c4f01239362149b853a9c94fb8c1b0e053 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/log/LoggingSeleniumWrapper.java @@ -0,0 +1,751 @@ +package org.olat.test.util.selenium.log; + +import junit.framework.AssertionFailedError; + +import org.apache.log4j.Logger; + +import com.thoughtworks.selenium.Selenium; +import com.thoughtworks.selenium.SeleniumException; + +public class LoggingSeleniumWrapper implements Selenium { + + private static int highestSeqNum_ = 0; + + private final int seqNum_ = highestSeqNum_++; + + private final Logger logger_; + private final Selenium delegate_; + + public LoggingSeleniumWrapper(Selenium delegate, Logger logger) { + delegate_ = delegate; + logger_ = logger; + logger_.info(getLogPrefixDetails()+" <init>"); + } + + @Override + public String toString() { + return getLogPrefixDetails()+super.toString(); + } + + private String getLogPrefixDetails() { + return "[seleniumwrapper-"+seqNum_+"] "; + } + + public void addLocationStrategy(String strategyName, + String functionDefinition) { + logger_.info(getLogPrefixDetails()+"addLocationStrategy: "+strategyName+": "+functionDefinition); + delegate_.addLocationStrategy(strategyName, functionDefinition); + } + + public void addSelection(String locator, String optionLocator) { + delegate_.addSelection(locator, optionLocator); + } + + public void allowNativeXpath(String allow) { + delegate_.allowNativeXpath(allow); + } + + public void altKeyDown() { + delegate_.altKeyDown(); + } + + public void altKeyUp() { + delegate_.altKeyUp(); + } + + public void answerOnNextPrompt(String answer) { + delegate_.answerOnNextPrompt(answer); + } + + public void assignId(String locator, String identifier) { + delegate_.assignId(locator, identifier); + } + + public void attachFile(String fieldLocator, String fileLocator) { + delegate_.attachFile(fieldLocator, fileLocator); + } + + + public void captureScreenshot(String filename) { + delegate_.captureScreenshot(filename); + } + + public void check(String locator) { + delegate_.check(locator); + } + + public void chooseCancelOnNextConfirmation() { + delegate_.chooseCancelOnNextConfirmation(); + } + + public void chooseOkOnNextConfirmation() { + delegate_.chooseOkOnNextConfirmation(); + } + + public void click(String locator) { + logger_.info(getLogPrefixDetails()+"click: "+locator); + if (!locator.startsWith("ui=")) { + //throw new AssertionError("click must use olat mapping file. add the following to it or find it there already: "+locator); + } + try{ + if (!delegate_.isElementPresent(locator)) { + System.err.println(getLogPrefixDetails()+"UI Element not found: "+locator); + logger_.warn(getLogPrefixDetails()+"UI Element not found: "+locator); + } + } catch(SeleniumException e) { + System.err.println(getLogPrefixDetails()+"Could not determine whether UI Element exists: "+locator); + System.err.println(getLogPrefixDetails()+"Got exception instead: "+e); + throw e; + } + try{ + delegate_.click(locator); + } catch(SeleniumException e) { + throw e; + } + } + + public void clickAt(String locator, String coordString) { + if (!locator.startsWith("ui=")) { + throw new AssertionError("click must use olat mapping file. add the following to it or find it there already: "+locator); + } + delegate_.clickAt(locator, coordString); + } + + public void close() { + delegate_.close(); + } + + public void contextMenu(String locator) { + delegate_.contextMenu(locator); + } + + public void contextMenuAt(String locator, String coordString) { + delegate_.contextMenuAt(locator, coordString); + } + + public void controlKeyDown() { + delegate_.controlKeyDown(); + } + + public void controlKeyUp() { + delegate_.controlKeyUp(); + } + + public void createCookie(String nameValuePair, String optionsString) { + delegate_.createCookie(nameValuePair, optionsString); + } + + public void deleteAllVisibleCookies() { + delegate_.deleteAllVisibleCookies(); + } + + public void deleteCookie(String name, String optionsString) { + delegate_.deleteCookie(name, optionsString); + } + + public void doubleClick(String locator) { + delegate_.doubleClick(locator); + } + + public void doubleClickAt(String locator, String coordString) { + delegate_.doubleClickAt(locator, coordString); + } + + public void dragAndDrop(String locator, String movementsString) { + delegate_.dragAndDrop(locator, movementsString); + } + + public void dragAndDropToObject(String locatorOfObjectToBeDragged, + String locatorOfDragDestinationObject) { + delegate_.dragAndDropToObject(locatorOfObjectToBeDragged, locatorOfDragDestinationObject); + } + + public void dragdrop(String locator, String movementsString) { + delegate_.dragdrop(locator, movementsString); + } + + public void fireEvent(String locator, String eventName) { + delegate_.fireEvent(locator, eventName); + } + + public void focus(String locator) { + delegate_.focus(locator); + } + + public String getAlert() { + return delegate_.getAlert(); + } + + public String[] getAllButtons() { + return delegate_.getAllButtons(); + } + + public String[] getAllFields() { + return delegate_.getAllFields(); + } + + public String[] getAllLinks() { + return delegate_.getAllLinks(); + } + + public String[] getAllWindowIds() { + return delegate_.getAllWindowIds(); + } + + public String[] getAllWindowNames() { + return delegate_.getAllWindowNames(); + } + + public String[] getAllWindowTitles() { + return delegate_.getAllWindowTitles(); + } + + public String getAttribute(String attributeLocator) { + return delegate_.getAttribute(attributeLocator); + } + + public String[] getAttributeFromAllWindows(String attributeName) { + return delegate_.getAttributeFromAllWindows(attributeName); + } + + public String getBodyText() { + return delegate_.getBodyText(); + } + + public String getConfirmation() { + return delegate_.getConfirmation(); + } + + public String getCookie() { + return delegate_.getCookie(); + } + + public String getCookieByName(String name) { + return delegate_.getCookieByName(name); + } + + public Number getCursorPosition(String locator) { + return delegate_.getCursorPosition(locator); + } + + public Number getElementHeight(String locator) { + return delegate_.getElementHeight(locator); + } + + public Number getElementIndex(String locator) { + return delegate_.getElementIndex(locator); + } + + public Number getElementPositionLeft(String locator) { + return delegate_.getElementPositionLeft(locator); + } + + public Number getElementPositionTop(String locator) { + return delegate_.getElementPositionTop(locator); + } + + public Number getElementWidth(String locator) { + return delegate_.getElementWidth(locator); + } + + public String getEval(String script) { + return delegate_.getEval(script); + } + + public String getExpression(String expression) { + return delegate_.getExpression(expression); + } + + public String getHtmlSource() { + return delegate_.getHtmlSource(); + } + + public String getLocation() { + return delegate_.getLocation(); + } + + public Number getMouseSpeed() { + return delegate_.getMouseSpeed(); + } + + public String getPrompt() { + return delegate_.getPrompt(); + } + + public String[] getSelectOptions(String selectLocator) { + return delegate_.getSelectOptions(selectLocator); + } + + public String getSelectedId(String selectLocator) { + return delegate_.getSelectedId(selectLocator); + } + + public String[] getSelectedIds(String selectLocator) { + return delegate_.getSelectedIds(selectLocator); + } + + public String getSelectedIndex(String selectLocator) { + return delegate_.getSelectedIndex(selectLocator); + } + + public String[] getSelectedIndexes(String selectLocator) { + return delegate_.getSelectedIndexes(selectLocator); + } + + public String getSelectedLabel(String selectLocator) { + return delegate_.getSelectedLabel(selectLocator); + } + + public String[] getSelectedLabels(String selectLocator) { + return delegate_.getSelectedLabels(selectLocator); + } + + public String getSelectedValue(String selectLocator) { + return delegate_.getSelectedValue(selectLocator); + } + + public String[] getSelectedValues(String selectLocator) { + return delegate_.getSelectedValues(selectLocator); + } + + public String getSpeed() { + return delegate_.getSpeed(); + } + + public String getTable(String tableCellAddress) { + return delegate_.getTable(tableCellAddress); + } + + public String getText(String locator) { + return delegate_.getText(locator); + } + + public String getTitle() { + return delegate_.getTitle(); + } + + public String getValue(String locator) { + return delegate_.getValue(locator); + } + + public boolean getWhetherThisFrameMatchFrameExpression( + String currentFrameString, String target) { + return delegate_.getWhetherThisFrameMatchFrameExpression(currentFrameString, target); + } + + public boolean getWhetherThisWindowMatchWindowExpression( + String currentWindowString, String target) { + return delegate_.getWhetherThisWindowMatchWindowExpression(currentWindowString, target); + } + + public Number getXpathCount(String xpath) { + return delegate_.getXpathCount(xpath); + } + + public void goBack() { + delegate_.goBack(); + } + + public void highlight(String locator) { + delegate_.highlight(locator); + } + + public void ignoreAttributesWithoutValue(String ignore) { + delegate_.ignoreAttributesWithoutValue(ignore); + } + + public boolean isAlertPresent() { + return delegate_.isAlertPresent(); + } + + public boolean isChecked(String locator) { + return delegate_.isChecked(locator); + } + + public boolean isConfirmationPresent() { + return delegate_.isConfirmationPresent(); + } + + public boolean isCookiePresent(String name) { + return delegate_.isCookiePresent(name); + } + + public boolean isEditable(String locator) { + return delegate_.isEditable(locator); + } + + public boolean isElementPresent(String locator) { + logger_.info(getLogPrefixDetails()+"isElementPresent: "+locator); + boolean elementPresent = false; + try{ + elementPresent = delegate_.isElementPresent(locator); + } finally { + logger_.info(getLogPrefixDetails()+"isElementPresent: "+locator+" => "+elementPresent); + } + return elementPresent; + } + + public boolean isOrdered(String locator1, String locator2) { + return delegate_.isOrdered(locator1, locator2); + } + + public boolean isPromptPresent() { + return delegate_.isPromptPresent(); + } + + public boolean isSomethingSelected(String selectLocator) { + return delegate_.isSomethingSelected(selectLocator); + } + + public boolean isTextPresent(String pattern) { + return delegate_.isTextPresent(pattern); + } + + public boolean isVisible(String locator) { + return delegate_.isVisible(locator); + } + + public void keyDown(String locator, String keySequence) { + delegate_.keyDown(locator, keySequence); + } + + public void keyDownNative(String keycode) { + delegate_.keyDownNative(keycode); + } + + public void keyPress(String locator, String keySequence) { + delegate_.keyPress(locator, keySequence); + } + + public void keyPressNative(String keycode) { + delegate_.keyPressNative(keycode); + } + + public void keyUp(String locator, String keySequence) { + delegate_.keyUp(locator, keySequence); + } + + public void keyUpNative(String keycode) { + delegate_.keyUpNative(keycode); + } + + public void metaKeyDown() { + delegate_.metaKeyDown(); + } + + public void metaKeyUp() { + delegate_.metaKeyUp(); + } + + public void mouseDown(String locator) { + delegate_.mouseDown(locator); + } + + public void mouseDownAt(String locator, String coordString) { + delegate_.mouseDownAt(locator, coordString); + } + + public void mouseMove(String locator) { + delegate_.mouseMove(locator); + } + + public void mouseMoveAt(String locator, String coordString) { + delegate_.mouseMoveAt(locator, coordString); + } + + public void mouseOut(String locator) { + delegate_.mouseOut(locator); + } + + public void mouseOver(String locator) { + delegate_.mouseOver(locator); + } + + public void mouseUp(String locator) { + delegate_.mouseUp(locator); + } + + public void mouseUpAt(String locator, String coordString) { + delegate_.mouseUpAt(locator, coordString); + } + + public void open(String url) { + delegate_.open(url); + } + + public void openWindow(String url, String windowID) { + delegate_.openWindow(url, windowID); + } + + public void refresh() { + delegate_.refresh(); + } + + public void removeAllSelections(String locator) { + delegate_.removeAllSelections(locator); + } + + public void removeSelection(String locator, String optionLocator) { + delegate_.removeSelection(locator, optionLocator); + } + + public void runScript(String script) { + delegate_.runScript(script); + } + + public void select(String selectLocator, String optionLocator) { + logger_.info(getLogPrefixDetails()+"select: "+selectLocator+", "+optionLocator); + delegate_.select(selectLocator, optionLocator); + } + + public void selectFrame(String locator) { + delegate_.selectFrame(locator); + } + + public void selectWindow(String windowID) { + delegate_.selectWindow(windowID); + } + + public void setBrowserLogLevel(String logLevel) { + delegate_.setBrowserLogLevel(logLevel); + } + + public void setContext(String context) { + delegate_.setContext(context); + } + + public void setCursorPosition(String locator, String position) { + delegate_.setCursorPosition(locator, position); + } + + public void setMouseSpeed(String pixels) { + delegate_.setMouseSpeed(pixels); + } + + public void setSpeed(String value) { + delegate_.setSpeed(value); + } + + public void setTimeout(String timeout) { + delegate_.setTimeout(timeout); + } + + public void shiftKeyDown() { + delegate_.shiftKeyDown(); + } + + public void shiftKeyUp() { + delegate_.shiftKeyUp(); + } + + public void shutDownSeleniumServer() { + delegate_.shutDownSeleniumServer(); + } + + public void start() { + delegate_.start(); + } + + public void stop() { + delegate_.stop(); + } + + public void submit(String formLocator) { + delegate_.submit(formLocator); + } + + public void type(String locator, String value) { + logger_.info(getLogPrefixDetails()+"type: "+locator+", "+value); + if (!locator.startsWith("ui=")) { + throw new AssertionError("type must use olat mapping file. add the following to it or find it there already: "+locator); + } + delegate_.type(locator, value); + } + + public void typeKeys(String locator, String value) { + if (!locator.startsWith("ui=")) { + throw new AssertionError("type must use olat mapping file. add the following to it or find it there already: "+locator); + } + delegate_.typeKeys(locator, value); + } + + public void uncheck(String locator) { + delegate_.uncheck(locator); + } + + public void waitForCondition(String script, String timeout) { + delegate_.waitForCondition(script, timeout); + } + + public void waitForFrameToLoad(String frameAddress, String timeout) { + delegate_.waitForFrameToLoad(frameAddress, timeout); + } + + public void waitForPageToLoad(String timeout) { + logger_.info(getLogPrefixDetails()+"waitForPageToLoad: "+timeout); + delegate_.waitForPageToLoad(timeout); + try{ + final String title = delegate_.getTitle(); + final String knownIssuesStr = "KnownIssueException"; + final String bodyText = delegate_.getBodyText(); + if ("OLAT - Error".equals(title)) { + if (!bodyText.contains(knownIssuesStr)) { + throw new AssertionFailedError("Red Screen encountered! See System.out for details!!!"); + } + } else if (title.contains("Error")) { + if (!bodyText.contains(knownIssuesStr)) { + throw new AssertionFailedError("Red Screen encountered! See System.out for details!!!"); + } + } else { + if (!bodyText.contains(knownIssuesStr)) { + if (bodyText.contains("An error occured")) { + throw new AssertionFailedError("Red Screen encountered! See System.out for details!!!"); + } else if (bodyText.contains("translation:::")) { + throw new AssertionFailedError("Translation Issue encountered! (translation::: found in text) See System.out for details!!!"); + } + } + } + } catch(Exception e) { + logger_.info(getLogPrefixDetails()+"waitForPageToLoad: couldn't fetch title or body. bummer. but never mind.: "+e); + } + } + + public void waitForPopUp(String windowID, String timeout) { + delegate_.waitForPopUp(windowID, timeout); + } + + public void windowFocus() { + delegate_.windowFocus(); + } + + public void windowMaximize() { + delegate_.windowMaximize(); + } + + @Override + public void addCustomRequestHeader(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.addCustomRequestHeader(arg0, arg1); + } + + @Override + public void addScript(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.addScript(arg0, arg1); + } + + @Override + public void captureEntirePageScreenshot(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.captureEntirePageScreenshot(arg0, arg1); + } + + @Override + public String captureEntirePageScreenshotToString(String arg0) { + // TODO Auto-generated method stub + return delegate_.captureEntirePageScreenshotToString(arg0); + } + + @Override + public String captureNetworkTraffic(String arg0) { + // TODO Auto-generated method stub + return delegate_.captureNetworkTraffic(arg0); + } + + @Override + public String captureScreenshotToString() { + // TODO Auto-generated method stub + return delegate_.captureScreenshotToString(); + } + + @Override + public void deselectPopUp() { + // TODO Auto-generated method stub + delegate_.deselectPopUp(); + } + + @Override + public void mouseDownRight(String arg0) { + // TODO Auto-generated method stub + delegate_.mouseDownRight(arg0); + } + + @Override + public void mouseDownRightAt(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.mouseDownRightAt(arg0, arg1); + } + + @Override + public void mouseUpRight(String arg0) { + // TODO Auto-generated method stub + delegate_.mouseUpRight(arg0); + } + + @Override + public void mouseUpRightAt(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.mouseUpRightAt(arg0, arg1); + } + + @Override + public void removeScript(String arg0) { + // TODO Auto-generated method stub + delegate_.removeScript(arg0); + } + + @Override + public String retrieveLastRemoteControlLogs() { + // TODO Auto-generated method stub + return delegate_.retrieveLastRemoteControlLogs(); + } + + @Override + public void rollup(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.rollup(arg0, arg1); + } + + @Override + public void selectPopUp(String arg0) { + // TODO Auto-generated method stub + delegate_.selectPopUp(arg0); + } + + @Override + public void setExtensionJs(String arg0) { + // TODO Auto-generated method stub + delegate_.setExtensionJs(arg0); + } + + @Override + public void showContextualBanner() { + // TODO Auto-generated method stub + delegate_.showContextualBanner(); + } + + @Override + public void showContextualBanner(String arg0, String arg1) { + // TODO Auto-generated method stub + delegate_.showContextualBanner(arg0, arg1); + } + + @Override + public void start(String arg0) { + // TODO Auto-generated method stub + delegate_.start(arg0); + } + + @Override + public void start(Object arg0) { + // TODO Auto-generated method stub + delegate_.start(arg0); + } + + @Override + public void useXpathLibrary(String arg0) { + // TODO Auto-generated method stub + delegate_.useXpathLibrary(arg0); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/CannotExecuteException.java b/src/test/java/org/olat/test/util/selenium/olatapi/CannotExecuteException.java new file mode 100644 index 0000000000000000000000000000000000000000..6ded01bc6ce24e546b216b0542ae967eabaa0b38 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/CannotExecuteException.java @@ -0,0 +1,40 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi; + +/** + * CannotExecuteException is thrown if a specific operation (for instance delete learning resource) + * cannot be executed because any reason (e.g. resource cannot be deleted since there is a reference to it). + * + * @author Lavinia Dumitrescu + * + */ +public class CannotExecuteException extends RuntimeException { + + /** + * @param arg0 + */ + public CannotExecuteException(String arg0) { + super(arg0); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/OLATSeleniumWrapper.java b/src/test/java/org/olat/test/util/selenium/olatapi/OLATSeleniumWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3e7f70494cc502ba7948d5ace373b4af681ec0ff --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/OLATSeleniumWrapper.java @@ -0,0 +1,98 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi; + +import junit.framework.Assert; + +import com.thoughtworks.selenium.Selenium; + +/** + * Generic superclass for all OLAT abstraction layer classes. + * + * @author Lavinia Dumitrescu + * + */ +public class OLATSeleniumWrapper extends Assert { + + protected Selenium selenium; + + /** + * It is recommended to check in the subclass's constructor that we're on the right page. + * @param selenium + */ + public OLATSeleniumWrapper(Selenium selenium) { + this.selenium = selenium; + } + + /** + * Provide access to the selenium instance, for the case a finer grained stepping is needed. + * @return + */ + public Selenium getSelenium() { + return selenium; + } + + /** + * Helper method. + * Use this instead of the selenium object. + * @param text + * @return + */ + public boolean isTextPresent(String text) { + return selenium.isTextPresent(text); + } + + /** + * Helper method + * Use this instead of the selenium method + * + * Check for the Element with given locator + * @param locator The locator for the element to check for + * @return true if the element with given locator exists, false otherwise + */ + public boolean isElementPresent(String locator){ + return selenium.isElementPresent(locator); + } + + /** + * Helper method. + * Only selects the iframe and types the text, back to the top frame. + * No save, finish is called. + * @param text + */ + public void typeInRichText(String text) { + // the description shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", text); + //selenium.selectFrame("relative=top"); + } + + public void sleepThread(int mills) { + try { + Thread.sleep(mills); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/OLATWorkflowHelper.java b/src/test/java/org/olat/test/util/selenium/olatapi/OLATWorkflowHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..e5dddfbc9bfa9dcf9d7aae98f23178393898fccd --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/OLATWorkflowHelper.java @@ -0,0 +1,126 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi; + + +import org.olat.test.util.selenium.olatapi.admin.Administration; +import org.olat.test.util.selenium.olatapi.components.ChatComponent; +import org.olat.test.util.selenium.olatapi.group.Groups; +import org.olat.test.util.selenium.olatapi.home.Home; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.selenium.olatapi.user.UserManagement; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the entry point for the OLAT abstraction around the selenium commands. + * + * @author Lavinia Dumitrescu + * + */ +public class OLATWorkflowHelper extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public OLATWorkflowHelper(Selenium selenium) { + super(selenium); + } + + /** + * Select the Learning resources tab and return the corresponding abstraction. + * @param selenium + */ + public LearningResources getLearningResources() { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + return new LearningResources(selenium); + } + + /** + * Selects the Groups tab and returns the corresponding abstraction. + * @return + */ + public Groups getGroups() { + selenium.click("ui=tabs::groups()"); + selenium.waitForPageToLoad("30000"); + //click show all groups, if "Show all" link present. + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + return new Groups(selenium); + } + /** + * Select the Home tab and return the corresponding abstraction. + * @param selenium + */ + public Home getHome() { + //we are on Home just after login + if(selenium.isTextPresent("Welcome to OLAT")) { + return new Home(selenium); + } + //if not already on Home, go to Home + selenium.click("ui=tabs::home()"); + selenium.waitForPageToLoad("30000"); + return new Home(selenium); + } + + public UserManagement getUserManagement() { + selenium.click("ui=tabs::userManagement()"); + selenium.waitForPageToLoad("30000"); + return new UserManagement(selenium); + } + + public Administration getAdministration() { + selenium.click("ui=tabs::administration()"); + selenium.waitForPageToLoad("30000"); + return new Administration(selenium); + } + + /*public HelpCourse getHelp() throws Exception{ + selenium.click("ui=home::topNav_olatHelp()"); + Thread.sleep(10000); + + //select window + System.out.println(" title: " + selenium.getAllWindowTitles()[0]); + System.out.println(" title: " + selenium.getAllWindowTitles()[1]); + selenium.selectWindow(selenium.getAllWindowTitles()[0]); + + Thread.sleep(10000); + return new HelpCourse(selenium); + }*/ + + + public void logout() { + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } + + public ChatComponent getChatComponent() { + return new ChatComponent(selenium); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/WorkflowHelper.java b/src/test/java/org/olat/test/util/selenium/olatapi/WorkflowHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..b48acc8c2da3257fcb642fe90a42834cce2c6010 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/WorkflowHelper.java @@ -0,0 +1,778 @@ +package org.olat.test.util.selenium.olatapi; + +import java.io.File; +import java.net.MalformedURLException; + +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.lr.LearningResources; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * This class contains helper methods used by tests in order to setup olat + * server(s) as single vm, cluster mode-single node, cluster-mode-multiple + * nodes. + * <p> + * + * @author Stefan + * + */ +public class WorkflowHelper { + + /** + * Find a file inside the seleniumtests dir. + * Returns file if any found, null otherwise. + * + * @param srcRelativeFilePath + * @return + */ + public static File locateFile(String srcRelativeFilePath) { + File f = new File("target/test-classes/" + srcRelativeFilePath); + if (f.exists()) { + return f; + } + f = new File("target/test-classes/" + Context.FILE_RESOURCES_PATH + srcRelativeFilePath); + if (f.exists()) { + return f; + } + return null; + } + + public static void deleteAllGroupsFromAuthor(OlatLoginInfos loginInfos) { + System.out.println("====================================="); + System.out.println("DELETE ALL GROUPS FROM: " + loginInfos.getUsername()); + System.out.println(" START"); + System.out.println("====================================="); + + Selenium selenium = Context.getContext().createSeleniumAndLogin(loginInfos); + selenium.click("ui=tabs::groups()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::menu_myProjectGroups()"); + selenium.waitForPageToLoad("30000"); + while(selenium.isElementPresent("ui=groups::content_deleteFirstGroup()")) { + selenium.click("ui=groups::content_deleteFirstGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Yes, we deleted a group!"); + } + + System.out.println("====================================="); + System.out.println("DELETE ALL GROUPS FROM: " + loginInfos.getUsername()); + System.out.println(" END"); + System.out.println("====================================="); + } + + public static void deleteAllLearningResourcesFromAuthor(String author) { + final long maxEnd = System.currentTimeMillis() + 900*1000 /*15 min*/; + System.out.println("====================================="); + System.out.println("DELETE ALL LEARNING RESOURCES FROM: " + author); + System.out.println(" START"); + System.out.println("====================================="); + + // get the list of all learning resources of the author + Selenium selenium = Context.getContext().createSeleniumAndLogin(); + while(System.currentTimeMillis()<maxEnd) { + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Author)", author); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + + // now loop through the list until there is no learning resource left to be deleted + if (!selenium.isElementPresent("ui=learningResources::content_firstLearningResourceInTable()")) { + break; + } + selenium.click("ui=learningResources::content_firstLearningResourceInTable()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("YESSS, WE DELETED A RESOURCE!!! "); + final String bodyText = selenium.getBodyText(); + if (bodyText.contains("cannot be deleted")) { + // fetch 'Used in course "CourseImportTestCourse-1227697859073"' + String nameOfReferredCourse = bodyText.substring(bodyText.indexOf("Used in course")+16); + nameOfReferredCourse = nameOfReferredCourse.substring(0, nameOfReferredCourse.indexOf("\"")); + System.out.println("Cannot delete resource since referenced in: " + nameOfReferredCourse); + selenium.click("ui=dialog::OK()"); + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", nameOfReferredCourse); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Author)", author); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + if (!selenium.isElementPresent("ui=learningResources::content_firstLearningResourceInTable()")) { + //throw new AssertionError("Got an ERROR box saying that the course is referenced. Tried to delete the referred course. But can't find it. Other author?"); + System.out.println("No Referred Course found! Maybe already deleted. Course deletion takes longer since 14.01.2010"); + } else { + selenium.click("ui=learningResources::content_firstLearningResourceInTable()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Referred Course deleted!"); + } + + } + } + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + selenium.close(); + selenium.stop(); + + System.out.println("====================================="); + System.out.println("DELETE ALL LEARNING RESOURCES FROM: " + author); + System.out.println(" END"); + System.out.println("====================================="); + } + + /** + * Deletes all learning resources found with the author + resourceTitle search filter. + * @param author + * @param resourceTitle + */ + public static void deleteLearningResources(String author, String resourceTitle) { + System.out.println("====================================="); + System.out.println("DELETE LEARNING RESOURCES FROM: " + author + " WITH TITLE: " + resourceTitle); + System.out.println(" START"); + System.out.println("====================================="); + + // get the list of all learning resources of the author + Selenium selenium = Context.getContext().createSeleniumAndLogin(); + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Author)", author); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", resourceTitle); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + + // now loop through the list until there is no learning resource left to be deleted + while(selenium.isElementPresent("ui=learningResources::content_firstLearningResourceInTable()")) { + selenium.click("ui=learningResources::content_firstLearningResourceInTable()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + selenium.close(); + selenium.stop(); + + System.out.println("====================================="); + System.out.println("DELETE ALL LEARNING RESOURCES FROM: " + author + " WITH TITLE: " + resourceTitle); + System.out.println(" END"); + System.out.println("====================================="); + } + + + public static void deleteAllCoursesNamed(String str) { + System.out.println("====================================="); + System.out.println("DELETE ALL COURSES NAMED: " + str); + System.out.println(" START"); + System.out.println("====================================="); + Selenium selenium = Context.getContext().createSeleniumAndLogin(); + int cnt = 0; + while (true) { + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", str); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + if (!selenium.isElementPresent("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + str + ")")) { + break; + } + selenium.click("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + str + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + cnt++; + } + selenium.close(); + selenium.stop(); + System.out.println("====================================="); + System.out.println("DELETE ALL COURSES NAMED: " + str); + System.out.println(" (deleted " + cnt + " courses)"); + System.out.println(" DONE"); + System.out.println("====================================="); + } + + public static OlatLoginInfos createUserIfNotExists( + OlatLoginInfos loginInfos, String username, String password, + boolean isSystemUser, boolean userManagementRole, + boolean groupManagementRole, boolean authorRole, + boolean systemAdminRole) throws InterruptedException { + + if (Context.getContext().getStandardAdminOlatLoginInfos(1) + .getUsername().equals(username)) { + throw new IllegalArgumentException( + "Thou shall not use an existing username! (" + username + + ")"); + } + if (Context.getContext().getStandardAuthorOlatLoginInfos(1) + .getUsername().equals(username)) { + throw new IllegalArgumentException( + "Thou shall not use an existing username! (" + username + + ")"); + } + if (Context.getContext().getStandardStudentOlatLoginInfos(1) + .getUsername().equals(username)) { + throw new IllegalArgumentException( + "Thou shall not use an existing username! (" + username + + ")"); + } + if (Context.getContext().getStandardGuestOlatLoginInfos(1) + .getUsername().equals(username)) { + throw new IllegalArgumentException( + "Thou shall not use an existing username! (" + username + + ")"); + } + + if (password.length() < 4) { + throw new IllegalArgumentException( + "password must be at least 4 characters"); + } + if (!password.matches(".*[0-9].*")) { + throw new IllegalArgumentException( + "password must contain an numerical value as well mate"); + } + if (username.matches(".*[A-Z].*")) { + throw new IllegalArgumentException( + "username must not contain CAPITAL letters!"); + } + System.out.println("connecting to " + loginInfos.getSeleniumHostname() + + "..."); + + Selenium selenium = Context.getContext().createSelenium(loginInfos); + System.out.println("connected."); + + System.out.println("Logging in to " + loginInfos.getFullOlatServerUrl() + + "..."); + OlatLoginHelper.olatLogin(selenium, loginInfos); + System.out.println("Logged in to " + loginInfos.getFullOlatServerUrl() + + "."); + + selenium.click("ui=tabs::userManagement()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + + if (selenium.isTextPresent("No user was found with these attributes.")) { + // then create the user + System.out.println("Create the user '" + username + + "', couldn't find it."); + selenium.click("ui=userManagement::menu_createUser()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=First name)", username); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Last name)", "GenByOlatServerSetupHelper"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=E-mail)", username + "" + System.currentTimeMillis() + "_seleniumuser@olat.uzh.ch"); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=Password)", password); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=Verify password)", password); + selenium.click("ui=userManagement::content_createUser_save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=tabs::userManagement()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + + if (selenium + .isTextPresent("No user was found with these attributes.")) { + throw new IllegalStateException("Couldnt create user " + + username); + } + // perfect! + } else { + // otherwise select the user and make sure the rights are set + // correctly + System.out.println("User '" + username + "' already exists."); + } + + // now adjust the role if necessary + selenium.click("ui=tabs::userManagement()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=commons::usertable_userlist_selectUserName(nameOfUser=" + + username + ")"); + selenium.waitForPageToLoad("30000"); + + selenium.click("ui=userManagement::content_userdetail_roles()"); + selenium.waitForPageToLoad("30000"); + + if (userManagementRole != selenium + .isChecked("ui=userManagement::content_userdetail_roles_isUsermanager()")) { + if (userManagementRole) { + selenium + .check("ui=userManagement::content_userdetail_roles_isUsermanager()"); + } else { + selenium + .uncheck("ui=userManagement::content_userdetail_roles_isUsermanager()"); + } + } + if (groupManagementRole != selenium + .isChecked("ui=userManagement::content_userdetail_roles_isGroupmanager()")) { + if (groupManagementRole) { + selenium + .check("ui=userManagement::content_userdetail_roles_isGroupmanager()"); + } else { + selenium + .uncheck("ui=userManagement::content_userdetail_roles_isGroupmanager()"); + } + } + if (authorRole != selenium + .isChecked("ui=userManagement::content_userdetail_roles_isAuthor()")) { + if (authorRole) { + selenium + .check("ui=userManagement::content_userdetail_roles_isAuthor()"); + } else { + selenium + .uncheck("ui=userManagement::content_userdetail_roles_isAuthor()"); + } + } + if (systemAdminRole != selenium + .isChecked("ui=userManagement::content_userdetail_roles_isAdmin()")) { + if (systemAdminRole) { + selenium + .check("ui=userManagement::content_userdetail_roles_isAdmin()"); + } else { + selenium + .uncheck("ui=userManagement::content_userdetail_roles_isAdmin()"); + } + } + + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + selenium.close(); + selenium.stop(); + + try { + return new OlatLoginInfos(loginInfos.getSeleniumHostname(), + loginInfos.getSeleniumBrowserId(), loginInfos + .getFullOlatServerUrl(), username, password); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + } + + /** + * 1. Imports course if not already imported 2. Modifies access - change + * course access to "All registered OLAT users" 3. Publishes course + * + * @param zippedCourse + * @param newTitleOfCourse + * @param newDescriptionOfCourse + * @throws InterruptedException + */ + public static void importCourse(File zippedCourse, String newTitleOfCourse, + String newDescriptionOfCourse) throws InterruptedException { + // check if course with newTitleOfCourse exists + boolean checkIfExists = false; + Selenium selenium_0 = Context.getContext().createSeleniumAndLogin(); + selenium_0.click("ui=tabs::learningResources()"); + selenium_0.waitForPageToLoad("30000"); + selenium_0.click("ui=learningResources::menu_searchForm()"); + selenium_0.waitForPageToLoad("30000"); + selenium_0.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", newTitleOfCourse); + selenium_0.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium_0.waitForPageToLoad("30000"); + checkIfExists = (selenium_0.isTextPresent(newTitleOfCourse)); + selenium_0.close(); + selenium_0.stop(); + if (checkIfExists) { + System.out.println("Course with title " + newTitleOfCourse + + " already exists, no need to import it!"); + return; + } + + String remoteFile = Context.getContext().provideFileRemotely(zippedCourse); + + System.out.println("==================="); + System.out.println("Course Import Start"); + System.out.println(" Course: " + newTitleOfCourse); + System.out.println(" File: " + zippedCourse.getAbsolutePath()); + System.out.println(" Remote: " + remoteFile); + System.out.println("==================="); + + Selenium selenium = Context.getContext().createSeleniumAndLogin(); + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_import_course()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::courseImport_uploadFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=upload::fileChooser()",remoteFile); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("60000"); + + while (!selenium.isElementPresent("ui=learningResources::dialog_title()")) { + for (int second = 0;; second++) { + if (second >= 120) + break; + try { + if (selenium + .isTextPresent("How do you wish to proceed?")) + break; + } catch (Exception e) { + } + Thread.sleep(500); + } + Thread.sleep(2000); + selenium.click("ui=learningResources::courseImport_importReferencesImport()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::courseImport_importReferencesContinue()"); + selenium.waitForPageToLoad("30000"); + } + // until the import is done + selenium.type("ui=learningResources::dialog_title()", newTitleOfCourse); + //the description shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", newDescriptionOfCourse); + //selenium.selectFrame("relative=top"); + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("60000"); + Thread.sleep(5000); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::dialog_startNo()"); + //selenium.waitForPageToLoad("30000"); + + selenium.click("ui=tabs::home()"); + selenium.waitForPageToLoad("30000"); + selenium.close(); + selenium.stop(); + System.out.println("================="); + System.out.println("Course Import End"); + System.out.println("================="); + + // modify property - change course access to "All registered OLAT users" + Selenium selenium_1 = Context.getContext().createSeleniumAndLogin(); + selenium_1.click("ui=tabs::learningResources()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=learningResources::menu_searchForm()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", newTitleOfCourse); + selenium_1.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + newTitleOfCourse + ")"); + selenium_1.waitForPageToLoad("30000"); + selenium_1 + .click("ui=learningResources::toolbox_learningResource_modifyProperties()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=learningResourcesModifieProperties::accessAllRegistered()"); + selenium_1.click("ui=commons::flexiForm_saveButton()"); + selenium_1.waitForPageToLoad("30000"); + + //select evidence of achievement and enable it if not already enabled + selenium_1.click("ui=learningResourcesModifieProperties::evidenceOfAchievement()"); + selenium_1.waitForPageToLoad("30000"); + boolean isEfficiencyStatementEnabled = selenium_1.isChecked("ui=learningResourcesModifieProperties::evidenceOfAchievementEnabled()"); + if(!isEfficiencyStatementEnabled) { + selenium_1.click("ui=learningResourcesModifieProperties::evidenceOfAchievementEnabled()"); + selenium_1.click("ui=commons::flexiForm_saveButton()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=learningResources::dialog_yes()"); + selenium_1.waitForPageToLoad("30000"); + } + + selenium_1.click("ui=overlay::overlayClose()"); + selenium_1.waitForPageToLoad("30000"); + //new step in modify properties + selenium_1.click("ui=learningResources::dialog_yes()"); + selenium_1.waitForPageToLoad("30000"); + + // publish course + selenium_1.click("ui=learningResources::content_showContent()"); + Thread.sleep(3000); + selenium_1.waitForPageToLoad("60000"); + selenium_1.click("ui=course::toolbox_courseTools_courseEditor()"); + Thread.sleep(1000); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=courseEditor::publishDialog_selectall()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=courseEditor::publishDialog_next()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=courseEditor::publishDialog_finish()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.click("ui=courseEditor::toolbox_editorTools_closeEditor()"); + selenium_1.waitForPageToLoad("30000"); + selenium_1.close(); + selenium_1.stop(); + } + + /** + * Administrator adds user with username as owner of the course with + * courseName. + * + * @param username + * @param courseName + * @throws Exception + */ + public static void addOwnerToLearningResource(String username, String courseName) throws Exception { + Selenium selenium = Context.getContext().createSeleniumAndLogin( + Context.getContext().getStandardAdminOlatLoginInfos(1)); + + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", courseName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + courseName + ")"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=learningResources::toolbox_learningResource_assignOwners()"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=learningResources::toolbox_learningResource_assignOwners_addOwner()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + + username + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.click("ui=overlay::overlayClose()"); + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * admnistrator adds user as tutor of the group + * + */ + public static void addTutorToGroup(String tutorUsername, String courseName, + String groupName) { + Selenium selenium = Context.getContext().createSeleniumAndLogin( + Context.getContext().getStandardAdminOlatLoginInfos(1)); + + openCourseAfterLogin(selenium, courseName); + selenium.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groupManagement::menu_allLearningGroups()"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=groupManagement::content_learningGroupTable_selectGroup(nameOfGroup=" + + groupName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=group::menu_administration()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=group::content_members_tabMembers()"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=groupManagement::content_learningGroupsEditor_addMembers_addTutor()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", tutorUsername); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium + .click("ui=groupManagement::content_learningGroupsEditor_addMembers_checkUser(username=" + + tutorUsername + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + //per default is "Send e-mail" not checked + //selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + Send e-mail + ")"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Enter "assessmentTool" course. + * + * @param selenium_ + */ + public static void openCourseAfterLogin(Selenium selenium_, String courseName) { + selenium_.click("ui=tabs::learningResources()"); + selenium_.waitForPageToLoad("30000"); + selenium_.click("ui=learningResources::menu_searchForm()"); + selenium_.waitForPageToLoad("30000"); + selenium_.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", courseName); + selenium_.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium_.waitForPageToLoad("30000"); + selenium_.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + courseName + ")"); + selenium_.waitForPageToLoad("30000"); + } + + /** + * Delete evidence of achievement for any course containing courseName and user. + * @param courseName + * @param userName + */ + public static void deleteEvidencesOfAchievement(String courseName, OlatLoginInfos olatLoginInfos) { + System.out.println("OlatServerSetupHelper - START deleteEvidenceOfAchievement"); + OLATWorkflowHelper workflow = Context.getContext().getOLATWorkflowHelper(olatLoginInfos); + workflow.getHome().getEvidencesOfAchievement().deleteAll(courseName); + System.out.println("OlatServerSetupHelper - END deleteEvidenceOfAchievement"); + } + + /** + * Helper method. + * Makes a copy of the course courseName, with the given name, and publishes as public visible. + * @param context + * @param courseName + * @param cloneCourseName + * @return returns true if course was successfully cloned. + */ + public static boolean cloneCourse(Context context, String courseName, String cloneCourseName) { + OLATWorkflowHelper workflow = context.getOLATWorkflowHelper(context.getStandardAdminOlatLoginInfos(1)); + LRDetailedView lRDetailedView = workflow.getLearningResources().searchResource(courseName, null); + LearningResources learningResources = lRDetailedView.copyLR(cloneCourseName, cloneCourseName + " description"); + LRDetailedView clonedLRDetailedView = learningResources.searchMyResource(cloneCourseName); + CourseEditor courseEditor = clonedLRDetailedView.showCourseContent().getCourseEditor(); + courseEditor.publishCourse(); + //close course editor to release the lock + courseEditor.closeToCourseRun().close(cloneCourseName); + return true; + } + + /*public static void deleteAllFromMyEntriesStartingWith(OlatLoginInfos loginInfos, String str) { + System.out.println("====================================="); + System.out.println("DELETE ALL FROM MYENTRIES STARTING WITH: " + str + " for user "+loginInfos.getUsername()); + System.out.println(" START"); + System.out.println("====================================="); + Selenium selenium = Context.getContext().createSeleniumAndLogin(loginInfos); + int cnt = 0; + boolean all = false; + while (true) { + System.out.println("COUNTER: "+cnt); + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::content_searchInTableField()", str); + try{ + System.out.println("Waiting 1 sec..."); + Thread.sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(System.out); + } + selenium.submit("ui=learningResources::content_searchInTableForm()"); + selenium.waitForPageToLoad("30000"); + + + // now loop through the list until there is no learning resource left to be deleted + if (!selenium.isElementPresent("ui=learningResources::content_firstLearningResourceInTable()")) { + all = true; + break; + } + selenium.click("ui=learningResources::content_firstLearningResourceInTable()"); + selenium.waitForPageToLoad("30000"); + String resourceTitle = selenium.getText("//div[span/a/span/text()='Back']//h4"); + System.out.println("Resource title: "+resourceTitle); + if (!resourceTitle.startsWith(str)) { + throw new IllegalStateException("resource title not what we were looking for: "+resourceTitle+". search str: "+str); + } + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + final String bodyText = selenium.getBodyText(); + if (bodyText.contains("cannot be deleted")) { + System.out.println("DELETION FAILED FOR SOME REASON... GIVING UP"); + System.out.println(bodyText); + break; + } else if (bodyText.contains("Entry deleted.")){ + System.out.println("YESSS, WE DELETED A RESOURCE!!! "); + cnt++; + continue; + } else { + System.out.println("COULDNT FIGURE OUT WHETHER DELETION WAS SUCCESSFUL OR NOT, GIVING UP..."); + System.out.println(bodyText); + break; + } + } + selenium.close(); + selenium.stop(); + System.out.println("====================================="); + System.out.println("DELETE ALL FROM MYENTRIES STARTING WITH: " + str); + System.out.println(" (deleted " + cnt + " entries, all="+all+")"); + System.out.println(" DONE"); + System.out.println("====================================="); + +} + +public static void deleteAllCoursesStartingWith(String str) { + System.out.println("====================================="); + System.out.println("DELETE ALL COURSES STARTING WITH: " + str); + System.out.println(" START"); + System.out.println("====================================="); + Selenium selenium = Context.getContext().createSeleniumAndLogin(); + int cnt = 0; + boolean all = false; + while (true) { + System.out.println("COUNTER: "+cnt); + selenium.click("ui=tabs::learningResources()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::content_searchForm_titleField()",str); + selenium.click("ui=learningResources::content_searchForm_search()"); + selenium.waitForPageToLoad("30000"); + + + // now loop through the list until there is no learning resource left to be deleted + if (!selenium.isElementPresent("ui=learningResources::content_firstLearningResourceInTable()")) { + all = true; + break; + } + selenium.click("ui=learningResources::content_firstLearningResourceInTable()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + final String bodyText = selenium.getBodyText(); + if (bodyText.contains("cannot be deleted")) { + System.out.println("DELETION FAILED FOR SOME REASON... GIVING UP"); + break; + } else if (bodyText.contains("Entry deleted.")){ + System.out.println("YESSS, WE DELETED A RESOURCE!!! "); + cnt++; + continue; + } else { + System.out.println("COULDNT FIGURE OUT WHETHER DELETION WAS SUCCESSFUL OR NOT, GIVING UP..."); + System.out.println(bodyText); + break; + } + } + selenium.close(); + selenium.stop(); + System.out.println("====================================="); + System.out.println("DELETE ALL COURSES STARTING WITH: " + str); + System.out.println(" (deleted " + cnt + " courses, all="+all+")"); + System.out.println(" DONE"); + System.out.println("====================================="); +}*/ + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/admin/Administration.java b/src/test/java/org/olat/test/util/selenium/olatapi/admin/Administration.java new file mode 100644 index 0000000000000000000000000000000000000000..ef2742259e29ca7d1a5d27519cf469ebc8a6d055 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/admin/Administration.java @@ -0,0 +1,35 @@ +package org.olat.test.util.selenium.olatapi.admin; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +public class Administration extends OLATSeleniumWrapper { + + public Administration(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public void editInfoMessage(String messageText) { + if(selenium.isElementPresent("ui=systemInformation::infoMsgTab()")) { + selenium.click("ui=systemInformation::infoMsgTab()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=systemInformation::infoMsgEditButton()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Message)", messageText); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean hasInfoMessage(String message) { + if(selenium.isElementPresent("ui=systemInformation::infoMsgTab()")) { + selenium.click("ui=systemInformation::infoMsgTab()"); + selenium.waitForPageToLoad("30000"); + } + return selenium.isTextPresent(message); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/components/ChatComponent.java b/src/test/java/org/olat/test/util/selenium/olatapi/components/ChatComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..9ad11a4dd8212316810d6119a7801899666e5347 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/components/ChatComponent.java @@ -0,0 +1,186 @@ +package org.olat.test.util.selenium.olatapi.components; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Utility class for the chat functionality. + * + * @author lavinia + * + */ +public class ChatComponent extends OLATSeleniumWrapper { + + public ChatComponent(Selenium selenium) { + super(selenium); + //TODO: check that Chat is configured for the tested instance + } + + /** COURSE CHAT */ + /** + * This is available in course. + */ + public void openChat(boolean showUser) { + selenium.mouseMoveAt("ui=courseChat::openCourseChat()", "300,300"); + selenium.click("ui=courseChat::openCourseChat()"); + selenium.waitForPageToLoad("90000"); + + sleepThread(6000); + + if(!selenium.isElementPresent("ui=courseChat::withinCourseChat()")) { + sleepThread(6000); + } + selenium.click("ui=courseChat::withinCourseChat()"); + selenium.waitForPageToLoad("30000"); + + if(showUser) { + toggleAnonymous(); + } + } + + public boolean isCourseChatAvailable() { + return selenium.isElementPresent("ui=courseChat::openCourseChat()"); + } + + + + /** + * COURSE CHAT. <br/> + * Toggle anonymous checkbox: show/hide username. + */ + public void toggleAnonymous() { + selenium.click("ui=courseChat::toggleAnonymous()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Works for any chat window: course/group/buddy. <br/> + * This should be called only after calling <code>openChat</code> or <code>openProjectGroupChat</code>. + * @param msg + */ + public void sendMessage(String msg, String chatroomLabel) { + selenium.type("ui=courseChat::labeledSendMsgInputField(label=" + chatroomLabel + ")", msg); + selenium.click("ui=courseChat::labeledSendMsgButton(label=" + chatroomLabel + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Works for any chat window: course/group/buddy, provided there is only one chat window open, + * else use the method with chatroomLabel parameter. <br/> + * This should be called only after calling <code>openChat</code> or <code>openProjectGroupChat</code>. + * @param msg + */ + public void sendMessage(String msg) { + selenium.type("ui=courseChat::sendMsgInputField()", msg); + selenium.click("ui=courseChat::sendMsgButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * BUDDY CHAT + */ + + /** + * BUDDY CHAT. <br/> + * clicks on the green star in upper right corner. + */ + public void openStatusChanger() { + selenium.click("ui=buddiesChat::openStatusChanger()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Works for any chat window: course/group/buddy. <br/> + * Closes the labeled chat window. + */ + public void closeExtWindow(String chatroomLabel) { + selenium.click("ui=buddiesChat::closeLabeledExtWindow(label=" + chatroomLabel + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Works for any chat window: course/group/buddy. <br/> + * Closes any chat window. + */ + public void closeExtWindow() { + selenium.click("ui=buddiesChat::closeExtWindow()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Open the buddies chat, this is available upon login in the upper right corner. + * @param fullname + */ + public void openBuddyChat(String fullname) { + selenium.click("ui=buddiesChat::showOnlineBuddies()"); + sleepThread(3000); + selenium.click("ui=buddiesChat::onlineBuddy(fullName=" + fullname + ")"); + selenium.waitForPageToLoad("30000"); + } + /** + * FIXME: how to switch to the new opened window? + * @param username + + public void openBuddyChat(String username) { + selenium.click("ui=buddiesChat::openOnlineUserList()"); + //selenium.waitForPageToLoad("90000"); + sleepThread(3000); + //selenium.selectWindow(selenium.getAllWindowTitles()[1]); + + selenium.selectWindow(selenium.getAllWindowTitles()[2]); + selenium.windowFocus(); + assertTrue(selenium.isTextPresent("List")); + }*/ + + /** + * This should be called only after calling <code>openBuddyChat</code>. + */ + public void sendBuddyMessage(String msg) { + selenium.type("ui=buddiesChat::sendMsgInputField()", msg); + selenium.click("ui=buddiesChat::sendMsgButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * This is available upon selection of a chat menu of a project group. + */ + public void openProjectGoupChat() { + selenium.click("ui=projectGroupChat::enterChatroom()"); + selenium.waitForPageToLoad("90000"); + + sleepThread(5000); + } + + /** + * Works for any chat window: course/group/buddy. <br/> + * Check if this chat window is still open. + * @param chatroomLabel + * @return + */ + public boolean isOpen(String chatroomLabel) { + return selenium.isElementPresent("ui=courseChat::labeledSendMsgInputField(label=" + chatroomLabel + ")"); + } + + /** + * BUDDY CHAT + * Is the green star in upper right corner available. + * @return + */ + public boolean isOpenStatusChangerAvailable() { + return selenium.isElementPresent("ui=buddiesChat::openStatusChanger()"); + } + + /** + * Works for any chat window: course/group/buddy. <br/> + * Check if a participant with this name is available for a chat window with this label. + * @param participantName + * @param chatroomLabel + * @return + */ + public boolean hasParticipant(String participantName, String chatroomLabel) { + //return selenium.isElementPresent("ui=courseChat::participant(participantName=" + participantName + ", chatroomLabel=" + chatroomLabel + ")"); + return selenium.isElementPresent("ui=courseChat::participant(participantName=" + participantName + ")"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/components/UserTableComponent.java b/src/test/java/org/olat/test/util/selenium/olatapi/components/UserTableComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..aee09ed323d6d608cc3be59d15996453e5eb4c5c --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/components/UserTableComponent.java @@ -0,0 +1,45 @@ +package org.olat.test.util.selenium.olatapi.components; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This a page component representing a user table. + * + * @author lavinia + * + */ +public class UserTableComponent extends OLATSeleniumWrapper { + + public UserTableComponent(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + /** + * This assumes that "Add users" button was pressed, just before. + */ + public void chooseUser(String userName) { + //fill in username info in the search mask + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + this.sleepThread(5000); + if(selenium.isElementPresent("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")")) { + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } else { + System.out.println("bummer! no such user found!"); + throw new IllegalStateException("No such user found!"); + } + } + + public void removeUser() { + + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/AssessmentEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/AssessmentEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..60654bb8bf3eee79668b6148fea2e641efe3465c --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/AssessmentEditor.java @@ -0,0 +1,84 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Assessment Course Element page. + * @author Lavinia Dumitrescu + * + */ +public class AssessmentEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public AssessmentEditor(Selenium selenium) { + super(selenium); + + // Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbAssessment_tabAssessment()")) { + throw new IllegalStateException("This is not the - Assessment course element - page"); + } + } + + /** + * By default the scoreGranted is "No" for a new AssessmentCourseElement. + * @param scoreGranted + * @param minScore + * @param maxScore + * @param typeOfDisplayAuto + * @param passedCutValue + */ + public void configure(Boolean scoreGranted, int minScore, int maxScore, Boolean typeOfDisplayAuto, int passedCutValue) { + if(selenium.isElementPresent("ui=courseEditor::content_bbAssessment_tabAssessment()")) { + selenium.click("ui=courseEditor::content_bbAssessment_tabAssessment()"); + selenium.waitForPageToLoad("30000"); + } + if(scoreGranted!=null && scoreGranted) { + if(selenium.isElementPresent("ui=courseEditor::content_assessmentElemConfig_scoreGranted()") && !selenium.isChecked("ui=courseEditor::content_assessmentElemConfig_scoreGranted()")) { + selenium.click("ui=courseEditor::content_assessmentElemConfig_scoreGranted()"); + } + selenium.waitForPageToLoad("30000"); + selenium.type("ui=courseEditor::content_assessmentElemConfig_minimumScore()", String.valueOf(minScore)); + selenium.type("ui=courseEditor::content_assessmentElemConfig_maximumScore()", String.valueOf(maxScore)); + if(typeOfDisplayAuto!=null && typeOfDisplayAuto) { + //selenium.check("ui=courseEditor::content_assessmentElemConfig_passedTypeAuto()"); //WARNING: check DOES NOT WORK!!! + selenium.click("ui=courseEditor::content_assessmentElemConfig_passedTypeAuto()"); + sleepThread(3000); + if(selenium.isElementPresent("ui=courseEditor::content_assessmentElemConfig_passedCutValue()")) { + selenium.type("ui=courseEditor::content_assessmentElemConfig_passedCutValue()", String.valueOf(passedCutValue)); + System.out.println("passedCutValue setted"); + } else if(selenium.isElementPresent("ui=courseEditor::content_assessmentElemConfig_passedCutValueErr()")) { + selenium.type("ui=courseEditor::content_assessmentElemConfig_passedCutValueErr()", String.valueOf(passedCutValue)); + System.out.println("passedCutValue setted"); + } + } + } else { + //default "No" + } + sleepThread(3000); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/BlogEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/BlogEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..1f696d80e5bc76cf5087f31acba8f507269115d8 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/BlogEditor.java @@ -0,0 +1,130 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + + +import org.olat.test.util.selenium.olatapi.lr.BlogResource; + +import com.thoughtworks.selenium.Selenium; + +/** + * Blog element configuration page in course editor. + * @author Sandra Arnold + * + */ +public class BlogEditor extends CourseElementEditor { + + //identifies the blogResource (e.g. for closing) + private String blogTitle; + + /** + * @param selenium + */ + public BlogEditor(Selenium selenium, String title) { + super(selenium); + blogTitle = title; + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + throw new IllegalStateException("This is not the - Blog Learning Content - page"); + } + } + + /** + * Select, import, create, replace, edit blog + * + * @param testTitle + */ + public void select(String blogTitle_) { + if(selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + selenium.click("ui=courseEditor::content_bbBlog_tabBlogLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbBlog_selectCreateImportBlog()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseBlog(nameOfBlog=" + blogTitle_ + ")"); + selenium.waitForPageToLoad("30000"); + blogTitle = blogTitle_; + } + + /** + * Creates new blog. + * @param blogTitle + * @param blogDescription + */ + public void create(String blogTitle, String blogDescription) { + if(selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + selenium.click("ui=courseEditor::content_bbBlog_tabBlogLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbBlog_selectCreateImportBlog()"); + selenium.waitForPageToLoad("30000"); + // TODO click "create", enter blogTitle and blogDescription, save, next, return to course editor, not clear where xpaths should be added + selenium.click("ui=courseEditor::content_bbBlog_create()"); + selenium.waitForPageToLoad("30000"); + + selenium.click("ui=learningResources::dialog_title()"); + selenium.type("ui=learningResources::dialog_title()", blogTitle); + + //SR: + //selenium.setSpeed("1000"); + + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", blogDescription); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("60000"); + } + + public void replace(String newBlogTitle) { + if(selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + selenium.click("ui=courseEditor::content_bbBlog_tabBlogLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbBlog_replaceBlog()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseBlog(nameOfBlog=" + newBlogTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * blog opens in new tab + * @return + */ + public BlogResource edit() { + if(selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + selenium.click("ui=courseEditor::content_bbBlog_tabBlogLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbBlog_editBlog()"); + selenium.waitForPageToLoad("30000"); + + return new BlogResource(selenium, blogTitle); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CPEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CPEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..bf50866f1d12e71bb4ad976d90d39da92760b5b0 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CPEditor.java @@ -0,0 +1,24 @@ +package org.olat.test.util.selenium.olatapi.course.editor; + +import com.thoughtworks.selenium.Selenium; + +public class CPEditor extends CourseElementEditor { + + public CPEditor(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public void select(String title) { + if(selenium.isElementPresent("ui=courseEditor::content_bbCP_tabLearningContentCP()")) { + selenium.click("ui=courseEditor::content_bbCP_tabLearningContentCP()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbCP_selectCreateImportCP()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseCP(name=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..651756c025e6a56c64b8fdb92b939bdb47b0641d --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseEditor.java @@ -0,0 +1,604 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.i18n.LocalStringProvider; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; + +import com.thoughtworks.selenium.Selenium; + +/** + * OLAT abstraction for the CourseEditor. + * One can get a CourseEditor instance either via the CourseRun, via the LRDetailedView, + * or via LearningResources createCourseAndStartEditing. + * <p> + * @author Lavinia Dumitrescu + * + */ +public class CourseEditor extends OLATSeleniumWrapper { + + //default titles for the course elements + public static final String STRUCTURE_TITLE = "Structure"; + public static final String SINGLE_PAGE_TITLE = "Single page"; + public static final String EXTERNAL_PAGE_TITLE = "External page"; + public static final String CP_LEARNING_CONTENT_TITLE = "CP learning content"; + public static final String SCORM_LEARNING_CONTENT_TITLE = "SCORM learning content"; + public static final String FORUM_COURSE_ELEM_TITLE = "Forum"; + public static final String WIKI_TITLE = "Wiki"; + public static final String FILE_DIALOG_TITLE = "File dialog"; + public static final String FOLDER_TITLE = "Folder"; + public static final String ASSESSMENT_TITLE = "Assessment"; + public static final String TASK_TITLE = "Task"; + public static final String TEST_TITLE = "Test"; + public static final String SELF_TEST_TITLE = "Self-test"; + public static final String QUESTIONNAIRE_TITLE = "Questionnaire"; + public static final String ENROLMENT_TITLE = "Enrolment"; + public static final String CONTACT_FORM_TITLE = "E-mail"; + public static final String BLOG_TITLE = "Blog"; + public static final String PODCAST_TITLE = "Podcast"; + public static final String TOPIC_ASSIGNMENT_TITLE = "Topic assignment"; + public static final String CALENDAR_TITLE = "Calendar"; + public static final String LTI_TITLE = "LTI page"; + + + //ALL VALID COURSE ELEMENT TYPES + public enum CourseElemTypes {STRUCTURE, SINGLE_PAGE, EXTERNAL_PAGE, CP_LEARNING_CONTENT, SCORM_LEARNING_CONTENT, + FORUM, WIKI, FILE_DIALOG, FOLDER, ASSESSMENT, TASK, TEST, SELF_TEST, QUESTIONNAIRE, ENROLMENT, CONTACT_FORM, BLOG, PODCAST, TOPIC_ASSIGNMENT, CALENDAR, + LTI_PAGE, INFO_MESSAGE} + + //ALL SUPPORTED INSERT TYPES + public enum InsertPosition {FIRST_CHILD_OF_ROOT, LAST_CHILD_OF_ROOT, FIRST_CHILD_OF_ELEMENT, FOLLOWING_SIBLING_OF_ELEMENT} + + private String currentElementTitle; + + /** + * + * @param selenium + */ + public CourseEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + //if(!selenium.isTextPresent("Close editor")) { + if(!selenium.isElementPresent("ui=courseEditor::toolbox_editorTools_closeEditor()")) { + //sleep and check again later + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + if(!selenium.isElementPresent("ui=courseEditor::toolbox_editorTools_closeEditor()")) { + throw new IllegalStateException("This is not the - Course editor - page"); + } + } + } + + + /** + * Insert a course element of the given type, with the newTitle if any provided (newTitle!=null). + * If newTitle==null the element gets the default title. + * @param elementType + * @param asFirstChildOfRoot, if true as first child, else as last child + * @param newTitle + * @return Returns an instance of the CourseElementEditor by default, + * or an EnrolmentEditor if an enrolment element was selected, + * or an TestElementEditor, + * SelfTestElementEditor, + * FolderEditor, + * SinglePageEditor, + * AssessmentEditor. + */ + public CourseElementEditor insertCourseElement(CourseElemTypes elementType, boolean asFirstChildOfRoot, String newTitle) { + clickInsertElement(elementType); + + if(asFirstChildOfRoot) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + } else { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsLastChild()"); + } + selenium.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium.waitForPageToLoad("30000"); + if(newTitle!=null) { + selenium.type("ui=courseEditor::content_TitleDescription_shortTitle()", newTitle); + selenium.click("ui=courseEditor::content_TitleDescription_save()"); + selenium.waitForPageToLoad("30000"); + } + + return returnCourseElement(elementType); + } + + /** + * Inserts a course element of the given type, in the given position (one of the possible InsertType) relative to the element with elementTitle. + * If newTitle==null the element gets the default title. <p> + * elementTitle must not be null if the insertType is InsertType.FIRST_CHILD_OF_ELEMENT or InsertType.FOLLOWING_SIBLING_OF_ELEMENT. + * <p> + * @param elementType + * @param insertType + * @param elementTitle + * @param newTitle + * @return + */ + public CourseElementEditor insertCourseElement(CourseElemTypes elementType, InsertPosition insertType, String elementTitle, String newTitle) { + clickInsertElement(elementType); + + if(InsertPosition.FIRST_CHILD_OF_ROOT.equals(insertType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + } else if(InsertPosition.LAST_CHILD_OF_ROOT.equals(insertType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsLastChild()"); + } else if(InsertPosition.FIRST_CHILD_OF_ELEMENT.equals(insertType) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFirstChild(title=" + elementTitle + ")"); + } else if(InsertPosition.FOLLOWING_SIBLING_OF_ELEMENT.equals(insertType) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFollowingSibling(title=" + elementTitle + ")"); + } else { + throw new IllegalStateException("InsertType or elementTitle are not acceptable!"); + } + + selenium.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium.waitForPageToLoad("30000"); + if(newTitle!=null) { + selenium.type("ui=courseEditor::content_TitleDescription_shortTitle()", newTitle); + selenium.click("ui=courseEditor::content_TitleDescription_save()"); + selenium.waitForPageToLoad("30000"); + } + + return returnCourseElement(elementType); + } + + private void clickInsertElement(CourseElemTypes elementType) { + if(CourseElemTypes.STRUCTURE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertStructure()"); + } else if(CourseElemTypes.SINGLE_PAGE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertSinglePage()"); + } else if(CourseElemTypes.EXTERNAL_PAGE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertExternalPage()"); + } else if(CourseElemTypes.CP_LEARNING_CONTENT.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertCP()"); + } else if(CourseElemTypes.SCORM_LEARNING_CONTENT.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertSCORM()"); + } else if(CourseElemTypes.FORUM.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertForum()"); + } else if(CourseElemTypes.WIKI.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertWiki()"); + } else if(CourseElemTypes.FILE_DIALOG.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertFileDialog()"); + } else if(CourseElemTypes.FOLDER.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertFolder()"); + } else if(CourseElemTypes.ASSESSMENT.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAssessment()"); + } else if(CourseElemTypes.TASK.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertTask()"); + } else if(CourseElemTypes.TEST.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertTest()"); + } else if (CourseElemTypes.SELF_TEST.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertSelfTest()"); + } else if(CourseElemTypes.QUESTIONNAIRE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertQuestionnaire()"); + } else if(CourseElemTypes.ENROLMENT.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertEnrolment()"); + } else if(CourseElemTypes.CONTACT_FORM.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertContactForm()"); + } else if(CourseElemTypes.BLOG.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertBlog()"); + } else if(CourseElemTypes.PODCAST.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertPodcast()"); + } else if(CourseElemTypes.TOPIC_ASSIGNMENT.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertTopicAssignment()"); + } else if(CourseElemTypes.CALENDAR.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertCalendar()"); + } else if(CourseElemTypes.LTI_PAGE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertLTIPage()"); + } else if(CourseElemTypes.INFO_MESSAGE.equals(elementType)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertInfoMessagePage()"); + } + selenium.waitForPageToLoad("60000"); + } + + private CourseElementEditor returnCourseElement(CourseElemTypes elementType) { + //check the inserted element type to decide the return type + if(CourseElemTypes.ENROLMENT.equals(elementType)) { + return new EnrolmentEditor(selenium); + } else if(CourseElemTypes.TEST.equals(elementType)) { + return new TestElementEditor(selenium); + } else if (CourseElemTypes.SELF_TEST.equals(elementType)) { + return new SelfTestElementEditor(selenium); + } else if(CourseElemTypes.FOLDER.equals(elementType)) { + return new FolderEditor(selenium); + } else if(CourseElemTypes.SINGLE_PAGE.equals(elementType)) { + return new SinglePageEditor(selenium); + } else if(CourseElemTypes.ASSESSMENT.equals(elementType)) { + return new AssessmentEditor(selenium); + } else if(CourseElemTypes.QUESTIONNAIRE.equals(elementType)) { + return new QuestionnaireElementEditor(selenium);// + } else if(CourseElemTypes.BLOG.equals(elementType)) { + return new BlogEditor(selenium, currentElementTitle); + } else if(CourseElemTypes.PODCAST.equals(elementType)) { + return new PodcastEditor(selenium, currentElementTitle); + } else if (CourseElemTypes.TOPIC_ASSIGNMENT.equals(elementType)) { + return new TopicAssignmentEditor(selenium); + } else if (CourseElemTypes.LTI_PAGE.equals(elementType)) { + return new LTIPageEditor(selenium); + } + return new CourseElementEditor(selenium); + } + + /** + * Deteles the current selected course element. + * @param elementTitle + */ + public void deleteCourseElement() { + selenium.click("ui=courseEditor::toolbox_modifyTools_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Restore the deleted course element. + */ + public void undeleteCourseElement() { + selenium.click("ui=courseEditor::content_undeleteCourseElement()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Moves the current selected course element and inserts it accordingly with the insertPosition. <p> + * elementTitle could be null if the insert position is relative to the root. + * @param insertPosition + * @param elementTitle + */ + public void moveCourseElement(InsertPosition insertPosition, String elementTitle) { + selenium.click("ui=courseEditor::toolbox_modifyTools_move()"); + selenium.waitForPageToLoad("30000"); + + if(InsertPosition.FIRST_CHILD_OF_ROOT.equals(insertPosition)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + } else if(InsertPosition.LAST_CHILD_OF_ROOT.equals(insertPosition)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsLastChild()"); + } else if(InsertPosition.FIRST_CHILD_OF_ELEMENT.equals(insertPosition) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFirstChild(title=" + elementTitle + ")"); + } else if(InsertPosition.FOLLOWING_SIBLING_OF_ELEMENT.equals(insertPosition) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFollowingSibling(title=" + elementTitle + ")"); + } else { + throw new IllegalStateException("InsertType or elementTitle are not acceptable!"); + } + + selenium.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium.waitForPageToLoad("30000"); + } + + public void copyCourseElement(InsertPosition insertPosition, String elementTitle) { + selenium.click("ui=courseEditor::toolbox_modifyTools_copy()"); + selenium.waitForPageToLoad("30000"); + + if(InsertPosition.FIRST_CHILD_OF_ROOT.equals(insertPosition)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + } else if(InsertPosition.LAST_CHILD_OF_ROOT.equals(insertPosition)) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsLastChild()"); + } else if(InsertPosition.FIRST_CHILD_OF_ELEMENT.equals(insertPosition) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFirstChild(title=" + elementTitle + ")"); + } else if(InsertPosition.FOLLOWING_SIBLING_OF_ELEMENT.equals(insertPosition) && elementTitle!=null && !elementTitle.equals("")) { + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsElementsFollowingSibling(title=" + elementTitle + ")"); + } else { + throw new IllegalStateException("InsertType or elementTitle are not acceptable!"); + } + + selenium.click("ui=courseEditor::toolbox_insertCourseElements_clickInsertCourseElement()"); + selenium.waitForPageToLoad("30000"); + } + + + + /** + * Call this if the CourseEditor was created via the LRDetailedView, + * or if the course was just imported/created. + * @return + */ + public LRDetailedView closeToLRDetailedView() { + selenium.click("ui=courseEditor::toolbox_editorTools_closeEditor()"); + selenium.waitForPageToLoad("30000"); + + return new LRDetailedView(selenium); + } + + + /** + * Call this if the CourseEditor was created via the CourseRun. + * @return + */ + public CourseRun closeToCourseRun() { + selenium.click("ui=courseEditor::toolbox_editorTools_closeEditor()"); + selenium.waitForPageToLoad("30000"); + + return new CourseRun(selenium); + } + + /** + * Straightforward course publish. + * Click "Publish", "Select all", "Next", select "All registered users", "Finish". + * + */ + public void publishCourse() { + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=courseEditor::publishDialog_selectall()")) { + selenium.click("ui=courseEditor::publishDialog_selectall()"); + // select-all is implemented locally in the client - without any request to the server + // selenium seems to not interpret this as a page-load consistently + // hence disabling the waitForPageToLoad and replacing it with a sleep of 1 sec + //selenium.waitForPageToLoad("30000"); + try{ + Thread.currentThread().sleep(1000); + } catch(InterruptedException ie) { + ie.printStackTrace(System.out); + } + } + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.select("ui=courseEditor::publishDialog_courseAccessDropDown()", "label=All registered OLAT users"); + //TODO: LD: add here check if next selectable, else finish + if(selenium.isElementPresent("ui=courseEditor::publishDialog_next()")) { + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::publishDialog_finish()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @return Returns true if anything found to be published, false otherwise. + */ + public boolean publishFirstChangedElement() { + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()")) { + System.out.println("There is something to publish ..."); + //if(!selenium.isTextPresent("The course is up to date.")) { + selenium.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + //TODO: LD: select only certain elements + if(selenium.isElementPresent("ui=courseEditor::publishDialog_next()")) { + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=courseEditor::publishDialog_next()")) { + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=courseEditor::publishDialog_finish()")) { + selenium.click("ui=courseEditor::publishDialog_finish()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Published finished!"); + } + return true; + } else { + System.out.println("No modifications to be published. The course is up to date. "); + selenium.click("ui=dialog::Cancel()"); + selenium.waitForPageToLoad("30000"); + } + return false; + } + + + /** + * Publishes only the root element, plus lots of asserts. + * @throws Exception + */ + public void publishCourseAfterCourseTitleChanged() throws Exception { + selenium.click("ui=courseEditor::toolbox_editorTools_publish()"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent("Publishing")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + + selenium.click("ui=courseEditor::publishDialog_howToPublish_firstTreeCheckbox()"); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + assertTrue(selenium.isTextPresent("No problems found")); + selenium.click("ui=courseEditor::publishDialog_next()"); + Thread.sleep(1000); + //pbl.confirm.users + //assertTrue(selenium.isTextPresent("Do you really want to publish this course?")); + assertTrue(selenium.isTextPresent(LocalStringProvider.COURSE_PUBLISH_CONFIRM)); + selenium.click("ui=courseEditor::publishDialog_finish()"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent("Selected modifications published successfully")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + } + + /** + * Selects the course element with the given title. + * @param title + * @return Returns an instance of the CourseElementEditor by default, + * or an EnrolmentEditor if an enrolment element was inserted, + * or an TestElementEditor, + * SelfTestElementEditor, + * FolderEditor, + * SinglePageEditor, + * AssessmentEditor. + */ + public CourseElementEditor selectCourseElement(String title) { + selectTruncatedTitle(title); + return getCurrentElement(); + } + + private void selectTruncatedTitle(String title) { + String truncatedTitle = title; + if(title.length()>22) { + truncatedTitle = title.substring(0, 22); + } + currentElementTitle = truncatedTitle; + selenium.click("ui=courseEditor::menu_link(link=" + truncatedTitle + ")"); + selenium.waitForPageToLoad("60000"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + } + } + + + public CourseElementEditor selectNextCourseElement(String title) { + //TODO: LD: implement this!!! + return null; + } + + /** + * Returns true if an element with this title is found. + * @param title + * @return + */ + public boolean containsElement(String title) { + String truncatedTitle = title; + if(title.length()>22) { + truncatedTitle = title.substring(0, 22); + } + currentElementTitle = truncatedTitle; + return selenium.isElementPresent("ui=courseEditor::menu_link(link=" + truncatedTitle + ")"); + } + + /** + * Selects the root if title provided, else assumes the root is selected. + * Per default the root is selected at open course editor. + * @return + */ + public StructureEditor getRoot (String title) { + if(title!=null) { + return (StructureEditor)selectCourseElement(title); + } else { + //hopefully the ROOT is selected!!!, if not bummer! + return (StructureEditor)getCurrentElement(); + } + } + + /** + * Automatically checks the type of the currently selected course element. + * + * @return the current selected course element. + */ + private CourseElementEditor getCurrentElement() { + if(selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + return new EnrolmentEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbFolder_tabFolderConfiguration()")) { + return new FolderEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbStructure_scoreTab()")) { + return new StructureEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()")) { + return new SelfTestElementEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbTest_tabTestConfiguration()")) { + return new TestElementEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbSinglePage_tabPageContent()") && selenium.isTextPresent("Single page")) { + //warning: it should have a long title containing "Single page" string in it, any better xpath? + return new SinglePageEditor(selenium); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbBlog_tabBlogLearningContent()")) { + return new BlogEditor(selenium, currentElementTitle); + } else if(selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + return new PodcastEditor(selenium, currentElementTitle); + } else if (selenium.isElementPresent("ui=courseEditor::content_lti_tabPageContent()") && selenium.isTextPresent("LTI page")) { + //warning: it should have a long title containing "Single page" string in it, any better xpath? + return new LTIPageEditor(selenium); + } + //TODO: LD: Add more course elements if necessary + return new CourseElementEditor(selenium); + } + + /** + * Select a wiki course element an choose wiki resource (from My entries) for it. + * @param elementTitle + * @param wikiTitle + */ + public void chooseMyWikiForElement(String elementTitle, String wikiTitle) { + selenium.click("ui=courseEditor::menu_link(link=" + elementTitle + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbWiki_tabWikiLearningContent()"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // nothing to do + } + selenium.click("ui=courseEditor::content_bbWiki_chooseWiki()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseWiki(nameOfWiki=" + wikiTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Choose wiki for the current selected course element by searching after wiki with wikiTitle and authorName. <p> + * This is an alternative to chooseMyWikiForElement (if myEntries list is too long). + * @param wikiTitle + * @param authorName + */ + public void chooseWikiForElement(String wikiTitle, String authorName) { + selenium.click("ui=courseEditor::content_bbWiki_tabWikiLearningContent()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbWiki_chooseWiki()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_search()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Author)", authorName); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", wikiTitle); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseWiki(nameOfWiki=" + wikiTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Shows course preview, and closes preview. + * + */ + public void preview() { + selenium.click("ui=courseEditor::toolbox_editorTools_coursePreview()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::preview_showCoursePreview()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::preview_closePreview()"); + selenium.waitForPageToLoad("30000"); + } + + public CoursePreview openPreview () { + selenium.click("ui=courseEditor::toolbox_editorTools_coursePreview()"); + selenium.waitForPageToLoad("30000"); + return new CoursePreview(selenium); + } + + + /** + * Selects the Storage folder. + * @return + */ + public Folder storageFolder() { + selenium.click("ui=courseEditor::toolbox_editorTools_storageFolder()"); + selenium.waitForPageToLoad("30000"); + return new Folder(selenium); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseElementEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseElementEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..07aa90347fff77101fbe6b6ae051002dfccde286 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CourseElementEditor.java @@ -0,0 +1,306 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Covers the common tabs of the course elements editor + * ("Title and description", "Visibility", and "Access" tabs). + * <p> + * + * + * @author Lavinia Dumitrescu + * + */ +public class CourseElementEditor extends OLATSeleniumWrapper { + + public enum ACCESS_TYPE {ACCESS, READ_ONLY, READ_AND_WRITE, MODERATE, CREATE_EDIT_WIKI, PRESENT}//MISSING FOR FILE_DIALOG, TASK, TOPIC_ASSIGNMENT,CALENDAR + + /** + * @param selenium + */ + protected CourseElementEditor(Selenium selenium) { + super(selenium); + sleepThread(3000); + // Check that we're on the right place + if (!selenium.isElementPresent("ui=courseEditor::content_TitleDescription_shortTitle()") + && !selenium.isElementPresent("ui=courseEditor::content_undeleteCourseElement()")) { + throw new IllegalStateException("This is not the - Course element - page"); + } + } + + public void setTitle(String title) { + selenium.type("ui=courseEditor::content_TitleDescription_shortTitle()", title); + selenium.click("ui=courseEditor::content_TitleDescription_save()"); + selenium.waitForPageToLoad("30000"); + } + + public void setDescription(String description) { + this.typeInRichText(description); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Changes visibility the current selected course element. + * + * @param groupName + */ + public void changeVisibilityDependingOnGroup(String groupName) { + selectVisibilityTab(); + selenium.click("ui=courseEditor::content_visibility_dependingGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_visibility_selectLearningGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=" + groupName + ")"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_visibility_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Changes access to the current selected course element, depending on + * assessment. + * + * @param title + */ + public void changeVisibilityDependingOnAssessment(String title) { + selectVisibilityTab(); + selenium.click("ui=courseEditor::content_visibility_dependingAssessment()"); + selenium.waitForPageToLoad("30000"); + selenium.select("ui=courseEditor::content_visibility_selectElement()", "label=" + title); + selenium.click("ui=courseEditor::content_visibility_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Changes access to the current selected course element, block for learners. <br/> + * Switches state. + * + */ + public void changeVisibilityBlockForLearners() { + selectVisibilityTab(); + selenium.click("ui=courseEditor::content_visibility_blockedForLearners()"); + selenium.waitForPageToLoad("30000"); + //Save button is no more visible in olat7 + if(selenium.isElementPresent("ui=courseEditor::content_visibility_save()")) { + selenium.click("ui=courseEditor::content_visibility_save()"); + selenium.waitForPageToLoad("30000"); + } + } + + private void selectVisibilityTab() { + if (selenium.isElementPresent("ui=courseEditor::content_visibility_tabVisibility()")) { + selenium.click("ui=courseEditor::content_visibility_tabVisibility()"); + selenium.waitForPageToLoad("30000"); + } + } + + private void selectAccessTab() { + if (selenium.isElementPresent("ui=courseEditor::content_access_tabAccess()")) { + selenium.click("ui=courseEditor::content_access_tabAccess()"); + selenium.waitForPageToLoad("30000"); + } + } + + + public boolean changeVisibilityExpertMode(boolean swichToExpertMode, String appendCondition) { + selectVisibilityTab(); + return appendCondition(swichToExpertMode, appendCondition); + } + + public boolean changeAccessExpertMode(boolean swichToExpertMode,String appendCondition) { + selectAccessTab(); + return appendCondition(swichToExpertMode, appendCondition); + } + + /** + * Append condition to the expert mode. + * Cases: + * 1. append condition only if the expert mode is already selected, + * 2. append condition in any case, that is select the expert mode before. + * + * @param swichToExpertMode + * @param appendCondition + */ + private boolean appendCondition(boolean swichToExpertMode, String appendCondition) { + if(swichToExpertMode && selenium.isElementPresent("ui=courseEditor::content_visibilityOrAccess_displayExpertMode()")) { + selenium.click("ui=courseEditor::content_visibility_displayExpertMode()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=courseEditor::content_visibilityOrAccess_displaySimpleMode()")) { + String expertRuleString = selenium.getValue("ui=commons::flexiForm_labeledTextArea(formElementLabel=Expert rule)"); + if(expertRuleString!=null && !expertRuleString.equals("")) { + expertRuleString += appendCondition; + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Expert rule)", expertRuleString); + //selenium.click("ui=commons::saveInput()"); + if(selenium.isElementPresent("ui=courseEditor::content_visibilityOrAccess_saveVisibilityExpertRule()")) { + selenium.click("ui=courseEditor::content_visibilityOrAccess_saveVisibilityExpertRule()"); + } else if(selenium.isElementPresent("ui=courseEditor::content_visibilityOrAccess_saveAccessExpertRule()")) { + selenium.click("ui=courseEditor::content_visibilityOrAccess_saveAccessExpertRule()"); + } else { + System.out.println("Warning: no save button found, could not save expert rule!"); + } + selenium.waitForPageToLoad("30000"); + return true; + } + } + return false; + } + + + + /** + * Changes access to the current selected course element depending on the + * input group. + * + * @param groupName + */ + public void changeAccessyDependingOnGroup(String groupName) { + selectAccessTab(); + selenium.click("ui=courseEditor::content_access_dependingGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_access_selectLearningGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=" + groupName + ")"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_access_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Edits the visibility info for the current selected course element. + * + * @param infoText + */ + public void editVisibilityInfo(String infoText) { + selectVisibilityTab(); + // the description shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", infoText); + //selenium.selectFrame("relative=top"); + + selenium.click("ui=courseEditor::content_visibility_saveInfo()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean isVisibilityDependingOnDate() { + selectVisibilityTab(); + if(selenium.isElementPresent("ui=courseEditor::content_visibility_dependingDate()")) { + return selenium.isChecked("ui=courseEditor::content_visibility_dependingDate()"); + } + return false; + } + + /** + * Changes visibility depending on date, + * assuming at least startDateString or endDateString must be not null or not empty! + * @param startDateString + * @param endDateString + */ + public boolean changeVisibilityDependingOnDate(String startDateString, String endDateString) { + if((startDateString==null||startDateString.equals("")) && (endDateString==null || endDateString.equals(""))) { + throw new IllegalStateException("at least startDateString or endDateString must be not null or not empty!"); + } + boolean changed = false; + selectVisibilityTab(); + if(!isVisibilityDependingOnDate()) { + selenium.check("ui=courseEditor::content_visibility_dependingDate()"); + selenium.waitForPageToLoad("30000"); + } + if(startDateString!=null && !startDateString.equals("")) { + selenium.type("ui=courseEditor::content_visibility_startDate()", startDateString); + changed = true; + } + if(endDateString!=null && !endDateString.equals("")) { + selenium.type("ui=courseEditor::content_visibility_endDate()", endDateString); + changed = true; + } + selenium.click("ui=courseEditor::content_visibility_save()"); + selenium.waitForPageToLoad("30000"); + return changed; + } + + public boolean isAccessDependingOnDate() { + selectAccessTab(); + if(selenium.isElementPresent("ui=courseEditor::content_access_dependingDate()")) { + return selenium.isChecked("ui=courseEditor::content_access_dependingDate()"); + } + return false; + } + + /** + * Changes access depending on date, + * assuming at least startDateString or endDateString must be not null or not empty! + * @param startDateString + * @param endDateString + */ + public boolean changeAccessDependingOnDate(String startDateString, String endDateString) { + selectAccessTab(); + if((startDateString==null||startDateString.equals("")) && (endDateString==null || endDateString.equals(""))) { + throw new IllegalStateException("at least startDateString or endDateString must be not null and not empty!"); + } + boolean changed = false; + if(!isAccessDependingOnDate()) { + selenium.check("ui=courseEditor::content_access_dependingDate()"); + selenium.waitForPageToLoad("30000"); + } + if(startDateString!=null && !startDateString.equals("")) { + selenium.type("ui=courseEditor::content_access_startDate()", startDateString); + changed = true; + } + if(endDateString!=null && !endDateString.equals("")) { + selenium.type("ui=courseEditor::content_access_endDate()", endDateString); + changed = true; + } + selenium.click("ui=courseEditor::content_access_save()"); + selenium.waitForPageToLoad("30000"); + return changed; + } + + /** + * Switch "Blocked for learners" access, for the given section, and save. + */ + public void changeAccessBlockedForLearners(ACCESS_TYPE accessType) { + selectAccessTab(); + if(ACCESS_TYPE.PRESENT.equals(accessType)) { + selenium.click("ui=courseEditor::content_access_blockedForLearners(fieldsetLegend=Present)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_access_saveAccess(fieldsetLegend=Present)"); + selenium.waitForPageToLoad("30000"); + } else if (ACCESS_TYPE.READ_AND_WRITE.equals(accessType)){ + selenium.click("ui=courseEditor::content_access_blockedForLearners(fieldsetLegend=Read and write)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_access_saveAccess(fieldsetLegend=Read and write)"); + selenium.waitForPageToLoad("30000"); + } else { + throw new UnsupportedOperationException("Not yet implemented"); + } + + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CoursePreview.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CoursePreview.java new file mode 100644 index 0000000000000000000000000000000000000000..764b4995b1db3f9cea845f4b27c0cb4eaac213f5 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/CoursePreview.java @@ -0,0 +1,50 @@ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +public class CoursePreview extends OLATSeleniumWrapper { + + public enum Role {REGISTERED_USER, GUEST, TUTOR, COURSE_OWNER, AUTHOR} + + public CoursePreview(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public CourseEditor closePreview() { + selenium.click("ui=courseEditor::preview_closePreview()"); + selenium.waitForPageToLoad("30000"); + return new CourseEditor(selenium); + } + + public void showPreview() { + selenium.click("ui=courseEditor::preview_showCoursePreview()"); + selenium.waitForPageToLoad("30000"); + } + + public void changeRole(Role role) { + if(Role.REGISTERED_USER.equals(role)) { + selenium.click("ui=courseEditor::preview_selectRole(role=role.student)"); + } else if(Role.GUEST.equals(role)) { + selenium.click("ui=courseEditor::preview_selectRole(role=role.guest)"); + } else if (Role.TUTOR.equals(role)) { + selenium.click("ui=courseEditor::preview_selectRole(role=role.coursecoach)"); + } else if (Role.COURSE_OWNER.equals(role)) { + selenium.click("ui=courseEditor::preview_selectRole(role=role.courseadmin)"); + } else if (Role.AUTHOR.equals(role)) { + selenium.click("ui=courseEditor::preview_selectRole(role=role.globalauthor)"); + } + } + + public void selectCourseElement(String title) { + selenium.click("ui=courseEditor::menu_link(link=" + title + ")"); + selenium.waitForPageToLoad("60000"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + } + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/EnrolmentEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/EnrolmentEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..ac68314d351665caf1609d0cc7b1796a9655c32d --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/EnrolmentEditor.java @@ -0,0 +1,127 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Enrolment course element editor. + * + * @author Lavinia Dumitrescu + * + */ +public class EnrolmentEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public EnrolmentEditor(Selenium selenium) { + super(selenium); + + // Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + throw new IllegalStateException("This is not the - Enrolment course element - page"); + } + } + + /** + * + * @param groupName + */ + public void selectLearningGroups(String groupName) { + if(selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + selenium.click("ui=courseEditor::content_bbEnrolment_tabConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=" + groupName + ")"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Selects groups in groupEnumerationString (Comma separated Value), + * and creates them if not already created. + * + * @param groupEnumerationString + */ + public void createAndSelectGroups(String groupEnumerationString) { + if(selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + selenium.click("ui=courseEditor::content_bbEnrolment_tabConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=commons::flexiForm_labeledTextInput(formElementLabel=Learning groups)")) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Learning groups)", groupEnumerationString); + selenium.click("ui=courseEditor::content_bbEnrolment_save()"); + selenium.waitForPageToLoad("30000"); + } else if(selenium.isElementPresent("ui=courseEditor::commons_groupBulk_selectGroupsIfError()")) { + //if error, type in the new groupEnumerationString + selenium.type("ui=courseEditor::commons_groupBulk_selectGroupsIfError()", groupEnumerationString); + selenium.click("ui=courseEditor::content_bbEnrolment_save()"); + selenium.waitForPageToLoad("30000"); + } + //if create button present, click create + if(selenium.isElementPresent("ui=courseEditor::commons_groupBulk_createGroups()")) { + selenium.click("ui=courseEditor::commons_groupBulk_createGroups()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_finishButton()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Check if the groupName is selected. + * + * @param groupName + * @return + */ + public boolean isGroupSelected(String groupName) { + if(selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + selenium.click("ui=courseEditor::content_bbEnrolment_tabConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + String groupValue = selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=Learning groups)"); + return groupValue.indexOf(groupName)!=-1; + } + + /** + * + * @param areaName + */ + public void selectLearningAreas(String areaName) { + if(selenium.isElementPresent("ui=courseEditor::content_bbEnrolment_tabConfiguration()")) { + selenium.click("ui=courseEditor::content_bbEnrolment_tabConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningArea()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_checkGroup(nameOfGroup=" + areaName + ")"); + selenium.click("ui=courseEditor::content_bbEnrolment_selectLearningGroupDialog_apply()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbEnrolment_save()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/FolderEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/FolderEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..60437b094320213c37c27444f8f04611ac5cadf1 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/FolderEditor.java @@ -0,0 +1,75 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Folder Course Element page. + * + * @author Lavinia Dumitrescu + * + */ +public class FolderEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public FolderEditor(Selenium selenium) { + super(selenium); + if(!selenium.isElementPresent("ui=courseEditor::content_bbFolder_tabFolderConfiguration()")) { + throw new IllegalStateException("This is not the - Folder editor - page"); + } + } + + /** + * Changes access to the current selected course element, blocked for learners read and write. + * + */ + public void changeAccessBlockForLearnersReadAndWrite() { + if(selenium.isElementPresent("ui=courseEditor::content_access_tabAccess()")) { + selenium.click("ui=courseEditor::content_access_tabAccess()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_access_blockedForLearnersReadAndWrite()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_access_saveReadAndWrite()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Changes access to the current selected course element, blocked for learners read only. + * + */ + public void changeAccessBlockForLearnersReadOnly() { + if(selenium.isElementPresent("ui=courseEditor::content_access_tabAccess()")) { + selenium.click("ui=courseEditor::content_access_tabAccess()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_access_blockedForLearnersReadOnly()"); + selenium.waitForPageToLoad("30000"); + //Save button no more visible in olat7 + /*selenium.click("ui=courseEditor::content_access_saveReadOnly()"); + selenium.waitForPageToLoad("30000");*/ + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/LTIPageEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/LTIPageEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..ca0cb988e376e8ec55890ffdd3d0e558b534e0ff --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/LTIPageEditor.java @@ -0,0 +1,95 @@ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +public class LTIPageEditor extends CourseElementEditor { + + public LTIPageEditor(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + private void selectPageContent() { + if (selenium.isElementPresent("ui=courseEditor::content_lti_tabPageContent()")) { + selenium.click("ui=courseEditor::content_lti_tabPageContent()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Accepts null as input params, if null ignore. + * If boolean false ignore, else click on checkbox (swich state). + * @param url + * @param key + * @param password + * @param sendNameToSupplierSwitch + * @param sendEmailToSupplierSwitch + * @param showInfoSentSwitch + */ + public void configurePage(String url, String key, String password, boolean sendNameToSupplierSwitch, boolean sendEmailToSupplierSwitch ,boolean showInfoSentSwitch) { + selectPageContent(); + if(url!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=URL)", url); + } + if(key!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Key)", key); + } + if(password!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Password)", password); + } + if(sendNameToSupplierSwitch) { + selenium.click("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Send name to provider)"); + } + if(sendEmailToSupplierSwitch) { + selenium.click("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Send e-mail address to provider)"); + } + if(showInfoSentSwitch) { + selenium.click("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Show information sent)"); + } + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + public LTIPreview showPreview(){ + selenium.click("ui=courseEditor::content_bbSinglePage_previewSinglePage()"); + selenium.waitForPageToLoad("30000"); + return new LTIPreview(this); + } + + /** + * Inner class since it could only be accessible via the parent class. + * @author lavinia + * + */ + public class LTIPreview extends OLATSeleniumWrapper { + + private LTIPageEditor lTIPageEditor; + + private LTIPreview(LTIPageEditor lTIPageEditor_) { + super(lTIPageEditor_.getSelenium()); + + lTIPageEditor = lTIPageEditor_; + } + + public boolean hasInfo(String info) { + //select iframe + selenium.selectFrame("//iframe[@id='IMSBasicLTIFrame']"); + boolean hasInfo = selenium.isTextPresent(info); + selenium.selectFrame("relative=top"); + return hasInfo; + } + + public LTIPageEditor closePreview() { + if(selenium.isElementPresent("ui=courseEditor::preview_closePreview()")) { + selenium.click("ui=courseEditor::preview_closePreview()"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Close preview - link not available"); + } + return lTIPageEditor; + } + + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/PodcastEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/PodcastEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..29af1fa4b04373973d52d61a19ea18a28dc3540e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/PodcastEditor.java @@ -0,0 +1,138 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + + +import org.olat.test.util.selenium.olatapi.lr.PodcastResource; + +import com.thoughtworks.selenium.Selenium; + +/** + * Podcast element configuration page in course editor. + * @author Sandra Arnold + * + */ +public class PodcastEditor extends CourseElementEditor { + + private String podcastTitle; + + /** + * @param selenium + */ + public PodcastEditor(Selenium selenium, String title) { + super(selenium); + podcastTitle = title; + + //Check that we're on the right place + //TODO tab + if(!selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + throw new IllegalStateException("This is not the - Podcast Learning Content - page"); + } + } + + /** + * Select, import, create, replace, edit podcast + * + * @param testTitle + */ + public void select(String podcastTitle) { + if(selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + selenium.click("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbPodcast_selectCreateImportPodcast()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_choosePodcast(nameOfPodcast=" + podcastTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Creates resource without starting editing. + * @param podcastTitle + * @param podcastDescription + */ + public void create(String podcastTitle, String podcastDescription) { + if(selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + selenium.click("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbPodcast_selectCreateImportPodcast()"); + selenium.waitForPageToLoad("30000"); + // TODO click "create", enter PodcastTitle and PodcastDescription, save, next, return to course editor, not clear where xpaths should be added + selenium.click("ui=courseEditor::content_bbPodcast_create()"); + selenium.waitForPageToLoad("30000"); + + selenium.click("ui=learningResources::dialog_title()"); + selenium.type("ui=learningResources::dialog_title()", podcastTitle); + + //SR: + //selenium.setSpeed("1000"); + + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", podcastDescription); + + //TODO: LD: add image for this learning resource + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("60000"); + } + + /** + * Choose new podcast. + * @param newPodcastTitle + */ + public void replace(String newPodcastTitle) { + if(selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + selenium.click("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbPodcast_replacePodcast()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_choosePodcast(nameOfPodcast=" + newPodcastTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Start editing resource. Podcast opens in new tab. + * @return + */ + public PodcastResource edit() { + if(selenium.isElementPresent("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()")) { + selenium.click("ui=courseEditor::content_bbPodcast_tabPodcastLearningContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbPodcast_editPodcast()"); + selenium.waitForPageToLoad("30000"); + + return new PodcastResource(selenium, podcastTitle); + } + + + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/QuestionnaireElementEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/QuestionnaireElementEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..2496164e1f9f83aa978b9b6d80861e7f29b6ba00 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/QuestionnaireElementEditor.java @@ -0,0 +1,64 @@ +package org.olat.test.util.selenium.olatapi.course.editor; + +import com.thoughtworks.selenium.Selenium; + +public class QuestionnaireElementEditor extends CourseElementEditor { + + public QuestionnaireElementEditor(Selenium selenium) { + super(selenium); + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbQuestionnaire_tabQuestionnaireConfiguration()")) { + throw new IllegalStateException("This is not the - Questionnaire configuration - page"); + } + } + + private void selectTabQuestionnaireConfiguration () { + if(selenium.isElementPresent("ui=courseEditor::content_bbQuestionnaire_tabQuestionnaireConfiguration()")) { + selenium.click("ui=courseEditor::content_bbQuestionnaire_tabQuestionnaireConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void chooseMyFile(String testTitle) { + selectTabQuestionnaireConfiguration(); + + selenium.click("ui=courseEditor::content_bbQuestionnaire_chooseFile()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_chooseQuestionnaire(nameOfQuestionnaire=" + testTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + public void configureQuestionnaireLayout(Boolean allowMenuNavigation, Boolean showMenuNavigation, Boolean allowCancel, Boolean allowSuspend) { + selectTabQuestionnaireConfiguration(); + + //TODO:LD: the XPATHs for test/survey/questionnaire are simply unnecessary replicated, remove the copies + if(showMenuNavigation!=null && showMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } else if(showMenuNavigation!=null && !showMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } + + if(allowMenuNavigation!=null && allowMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //check + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } else if(allowMenuNavigation!=null && !allowMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //uncheck + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } + + if(allowCancel!=null && allowCancel && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()"); + } else if(allowCancel!=null && !allowCancel && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()")){ + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()"); + } + + if(allowSuspend!=null && allowSuspend && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } else if(allowSuspend!=null && !allowSuspend && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")){ + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } + selenium.click("ui=commons::flexiForm_saveButton()"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SelfTestElementEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SelfTestElementEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..4329dde6bcc096f2b096d24aeea6bc15f09c20f6 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SelfTestElementEditor.java @@ -0,0 +1,105 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + + +import com.thoughtworks.selenium.Selenium; + +/** + * Self-Test element configuration page in course editor. + * @author Lavinia Dumitrescu + * + */ +public class SelfTestElementEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public SelfTestElementEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()")) { + throw new IllegalStateException("This is not the - Self-test configuration - page"); + } + } + + /** + * Choose the test file for this TestElement. + * + * @param testTitle + */ + public void chooseMyFile(String testTitle) { + if(selenium.isElementPresent("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()")) { + selenium.click("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbSelfTest_chooseFile()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + //if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::commons_chooseLr_chooseTest(nameOfTest=" + testTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Configure Layout. + * There is only a partial coverage of the possible configuration. + * + * @param allowMenuNavigation + * @param showMenuNavigation + * @param allowCancel + * @param allowSuspend + */ + public void configureSelfTestLayout(Boolean allowMenuNavigation, Boolean showMenuNavigation, Boolean allowCancel, Boolean allowSuspend) { + if(selenium.isElementPresent("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()")) { + selenium.click("ui=courseEditor::content_bbSelfTest_tabSelfTestConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + if(showMenuNavigation!=null && showMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } else if(showMenuNavigation!=null && !showMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } + + if(allowMenuNavigation!=null && allowMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //check + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } else if(allowMenuNavigation!=null && !allowMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //uncheck + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } + //self-tests always have a cancel button, so no need to configure this + + if(allowSuspend!=null && allowSuspend && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } else if(allowSuspend!=null && !allowSuspend && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")){ + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } + selenium.click("ui=commons::flexiForm_saveButton()"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SinglePageEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SinglePageEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..f9aa3b7b9095aefc27a66a5663d66fdfc8e42b19 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/SinglePageEditor.java @@ -0,0 +1,115 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.CannotExecuteException; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Single page - Page content editor. + * + * @author Lavinia Dumitrescu + * + */ +public class SinglePageEditor extends CourseElementEditor { + + public enum SELECT_TYPE {CREATE, CHOOSE_FROM_STORAGE_FOLDER, UPLOAD_TO_STORAGE_FOLDER}; + + /** + * @param selenium + */ + public SinglePageEditor(Selenium selenium) { + super(selenium); + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbSinglePage_tabPageContent()")) { + throw new IllegalStateException("This is not the - Single page - page"); + } + } + + /** + * Replace page, if possible. + * Throws CannotExecuteException if button not available. + * @param type + * @param title + * @throws CannotExecuteException + */ + public void replacePage(SELECT_TYPE type, String title) { + if (selenium.isElementPresent("ui=courseEditor::content_bbSinglePage_tabPageContent()")) { + selenium.click("ui=courseEditor::content_bbSinglePage_tabPageContent()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=courseEditor::content_bbSinglePage_replacePage()")) { + selenium.click("ui=courseEditor::content_bbSinglePage_replacePage()"); + selenium.waitForPageToLoad("30000"); + if(SELECT_TYPE.UPLOAD_TO_STORAGE_FOLDER.equals(type)) { + selenium.type("ui=upload::fileChooser()", title); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + } else if(SELECT_TYPE.CHOOSE_FROM_STORAGE_FOLDER.equals(type)) { + //TODO: LD: add code + } else if(SELECT_TYPE.CREATE.equals(type)) { + //TODO: LD: Add code + } + + } else { + throw new IllegalStateException("Replace page - button not available!"); + } + } + + public void createHTMLPage(String fileName, String content) { + if (selenium.isElementPresent("ui=courseEditor::content_bbSinglePage_tabPageContent()")) { + selenium.click("ui=courseEditor::content_bbSinglePage_tabPageContent()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbSinglePage_selectOrCreatePage()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=New HTML page)", fileName); + selenium.click("ui=commons::flexiForm_createButton()"); + selenium.waitForPageToLoad("30000"); + this.typeInRichText(content); + selenium.click("ui=courseEditor::content_bbSinglePage_saveAndClose()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Show the Preview page. + * + */ + public void preview() { + selenium.click("ui=courseEditor::content_bbSinglePage_previewSinglePage()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Close the preview + * + */ + public void closePreview() { + if(selenium.isElementPresent("ui=courseEditor::preview_closePreview()")) { + selenium.click("ui=courseEditor::preview_closePreview()"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Close preview - link not available"); + } + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/StructureEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/StructureEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..58cb3643f88bec3ec62957239649adb8c64e9ef0 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/StructureEditor.java @@ -0,0 +1,55 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Structure Course Element page. + * @author Lavinia Dumitrescu + * + */ +public class StructureEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public StructureEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbStructure_scoreTab()")) { + throw new IllegalStateException("This is not the - Structure element - page"); + } + } + + public void setMinimumScore(int score) { + if(selenium.isElementPresent("ui=courseEditor::content_bbStructure_scoreTab()")) { + selenium.click("ui=courseEditor::content_bbStructure_scoreTab()"); + selenium.waitForPageToLoad("30000"); + } + selenium.type("ui=courseEditor::content_bbStructure_minimumScore()", String.valueOf(score)); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TestElementEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TestElementEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..09552d5ded704946c6fc748483fb640af2be183e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TestElementEditor.java @@ -0,0 +1,141 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.editor; + + +import com.thoughtworks.selenium.Selenium; + +/** + * Test element configuration page in course editor. + * @author Lavinia Dumitrescu + * + */ +public class TestElementEditor extends CourseElementEditor { + + /** + * @param selenium + */ + public TestElementEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=courseEditor::content_bbTest_tabTestConfiguration()")) { + throw new IllegalStateException("This is not the - Test configuration - page"); + } + } + + /** + * Choose the test file for this TestElement. + * + * @param testTitle + */ + public void chooseMyFile(String testTitle) { + if(selenium.isElementPresent("ui=courseEditor::content_bbTest_tabTestConfiguration()")) { + selenium.click("ui=courseEditor::content_bbTest_tabTestConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // nothing to do + } + selenium.click("ui=courseEditor::content_bbTest_chooseFile()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::commons_chooseLr_myEntries()"); + selenium.waitForPageToLoad("30000"); + //if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::commons_chooseLr_chooseTest(nameOfTest=" + testTitle + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Configure Layout. + * There is only a partial coverage of the possible configuration. + * + * @param allowMenuNavigation should be null if default, true or false otherwise + * @param showMenuNavigation should be null if default, true or false otherwise + * @param allowCancel should be null if default, true or false otherwise + * @param allowSuspend should be null if default, true or false otherwise + * @param maxNumApproaches greater the 0 if set to some value + * @param displayResultsOnTestHomepage should be null if default, true or false otherwise + */ + public void configureTestLayout(Boolean allowMenuNavigation, Boolean showMenuNavigation, Boolean allowCancel, Boolean allowSuspend, + int maxNumApproaches, Boolean displayResultsOnTestHomepage) { + if(selenium.isElementPresent("ui=courseEditor::content_bbTest_tabTestConfiguration()")) { + selenium.click("ui=courseEditor::content_bbTest_tabTestConfiguration()"); + selenium.waitForPageToLoad("30000"); + } + + if(maxNumApproaches>0) { + if(!selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_limitNumOfAttempts()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_limitNumOfAttempts()"); + } + try { + Thread.sleep(5000); //sleep + } catch (InterruptedException e) { + } + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Maximum number of attempts)", String.valueOf(maxNumApproaches)); + } + + //boolean isShowMenuNavigationPresent = selenium.isElementPresent("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + //System.out.println("isShowMenuNavigationPresent: " + isShowMenuNavigationPresent); + if(showMenuNavigation!=null && showMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } else if(showMenuNavigation!=null && !showMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()")) { + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_showMenuNavigation()"); + } + + if(allowMenuNavigation!=null && allowMenuNavigation && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //check + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } else if(allowMenuNavigation!=null && !allowMenuNavigation && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()")) { + //uncheck + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowMenuNavigation()"); + } + + if(allowCancel!=null && allowCancel && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()"); + } else if(allowCancel!=null && !allowCancel && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()")){ + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowCancel()"); + } + + if(allowSuspend!=null && allowSuspend && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } else if(allowSuspend!=null && !allowSuspend && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()")){ + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_allowSuspend()"); + } + + if(displayResultsOnTestHomepage!=null && displayResultsOnTestHomepage && !selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_displayResultsOnTestHomepage()")) { + selenium.click("ui=courseEditor::content_bbTest_layoutParameters_displayResultsOnTestHomepage()"); + } else if(displayResultsOnTestHomepage!=null && !displayResultsOnTestHomepage && selenium.isChecked("ui=courseEditor::content_bbTest_layoutParameters_displayResultsOnTestHomepage()")) { + selenium.uncheck("ui=courseEditor::content_bbTest_layoutParameters_displayResultsOnTestHomepage()"); + } + //TODO: LD: there are more parameters to configure, config only if neccessary! + selenium.click("ui=commons::flexiForm_saveButton()"); + //selenium.waitForPageToLoad("30000"); + + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TopicAssignmentEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TopicAssignmentEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..57eb27d93099d0a95dfd74cf118ed71fe6a844ee --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/editor/TopicAssignmentEditor.java @@ -0,0 +1,89 @@ +package org.olat.test.util.selenium.olatapi.course.editor; + +import org.olat.test.util.selenium.olatapi.components.UserTableComponent; + +import com.thoughtworks.selenium.Selenium; + +public class TopicAssignmentEditor extends CourseElementEditor { + + public TopicAssignmentEditor(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + private void selectConfigurationTab() { + if(selenium.isElementPresent("ui=courseEditor::content_bbTopicAssignment_tabConfig()")) { + selenium.click("ui=courseEditor::content_bbTopicAssignment_tabConfig()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * It assumes that there are no default values selected. <br/> + * If limitNumOfTopics is true, topicLimit must be >0. + * If acceptParticipants is true, onlyOneTopic is relevant, else not. + * + * @param limitNumOfTopics + * @param topicLimit + * @param acceptParticipants + * @param onlyOneTopic + */ + public void configure (boolean limitNumOfTopics, int topicLimit, boolean acceptParticipants, boolean onlyOneTopic) { + selectConfigurationTab(); + if(limitNumOfTopics) { + selenium.click("ui=courseEditor::content_bbTopicAssignment_topicsPerParticipant()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=courseEditor::content_bbTopicAssignment_howManyTopicsPerParticipant()",String.valueOf(topicLimit)); + } + if(acceptParticipants) { + selenium.click("ui=courseEditor::content_bbTopicAssignment_topicSelectionAccept()"); + selenium.waitForPageToLoad("30000"); + if(!selenium.isElementPresent("ui=courseEditor::content_bbTopicAssignment_onlyOneTopicAllowed()")){ + selenium.click("ui=courseEditor::content_bbTopicAssignment_topicSelectionAccept()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::content_bbTopicAssignment_onlyOneTopicAllowed()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::content_bbTopicAssignment_saveConfig()"); + selenium.waitForPageToLoad("30000"); + } + + } + + private void selectPersonsInCharge() { + if(selenium.isElementPresent("ui=courseEditor::content_bbTopicAssignment_tabPersons()")) { + selenium.click("ui=courseEditor::content_bbTopicAssignment_tabPersons()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Add user(s) with this userNamePrefix. + * @param userNamePrefix + */ + public void addUsers(String userNamePrefix) { + selectPersonsInCharge(); + //select all users starting with userNamePrefix + selenium.click("ui=commons::usertable_addUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userNamePrefix); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + sleepThread(5000); + selenium.click("ui=commons::usertable_adduser_selectAll()"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + sleepThread(3000); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + } + + public void addUser(String userName) { + selectPersonsInCharge(); + selenium.click("ui=commons::usertable_addUsers()"); + selenium.waitForPageToLoad("30000"); + UserTableComponent userTable = new UserTableComponent(selenium); + userTable.chooseUser(userName); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentElement.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentElement.java new file mode 100644 index 0000000000000000000000000000000000000000..a25cac2dd60b98e4e453d57ba5a078046cd1720e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentElement.java @@ -0,0 +1,58 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Represents an Assessment course element in course run. + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentElement extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public AssessmentElement(Selenium selenium) { + super(selenium); + // Check that we're on the right place + if(!selenium.isElementPresent("ui=course::content_assessment_summaryOfScore()")) { + throw new IllegalStateException("This is not the - Assessment course element run - page"); + } + } + + /** + * + * @return the achieved score, if any, throws IllegalStateException otherwise. + */ + public String getScore() { + if(selenium.isElementPresent("ui=qti::yourScore()")) { + return selenium.getText("ui=qti::yourScore()"); + } + throw new IllegalStateException("There is no score information to be displayed yet."); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentForm.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentForm.java new file mode 100644 index 0000000000000000000000000000000000000000..ab8629b4fc3a3c4f06d0b900c665b7f8678c6510 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentForm.java @@ -0,0 +1,150 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the AssessmentForm page abstraction. + * TODO: LD: add methods for comments, and test if setComments/getComments work! + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentForm extends OLATSeleniumWrapper { + + public static final String PASSED_NO_INFO = "undefined"; + public static final String PASSED_YES = "true"; + public static final String PASSED_NO = "false"; + + /** + * @param selenium + */ + public AssessmentForm(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=commons::flexiForm_labeledTextInput(formElementLabel=Score)") + && !selenium.isElementPresent("ui=course::assessment_setPassedYes()")) { + //no set score and no set passed present + throw new IllegalStateException("This is not the - Assessment form - page"); + } + } + + /** + * Only type the score. + * Call save to commit the change. + * + * @param score + */ + public void setScore(double score) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Score)", String.valueOf(score)); + } + + public String getScore() { + return selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=Score)"); + } + + public String getMinScore() { + return selenium.getText("ui=course::assessment_minMaxScore(title=Minimum score)"); + } + + public String getMaxScore() { + return selenium.getText("ui=course::assessment_minMaxScore(title=Maximum score)"); + } + + public String getPassedCutScore() { + return selenium.getText("ui=course::assessment_minMaxScore(title=Passed cut value)"); + } + + /** + * Only set passed info. + * Call save to commit the change. + * + * @param passed + */ + public void setPassed(Boolean passed) { + if(passed==null) { + selenium.click("ui=course::assessment_setPassedNoInfo()"); + } else if(passed) { + selenium.click("ui=course::assessment_setPassedYes()"); + } else { + selenium.click("ui=course::assessment_setPassedNo()"); + } + } + + public String getPassed() { + if(selenium.isChecked("ui=course::assessment_setPassedYes()")) + return PASSED_YES; + if(selenium.isChecked("ui=course::assessment_setPassedNo()")) + return PASSED_NO; + + return PASSED_NO_INFO; + } + + public void setAttempts(int attempts) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Number of attempts)", String.valueOf(attempts)); + } + + public String getAttempts() { + return selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=Number of attempts)"); + } + + public void setUserComments(String text) { + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Comments for users)", String.valueOf(text)); + } + + public String getUserComment() { + return selenium.getValue("ui=commons::flexiForm_labeledTextArea(formElementLabel=Comments for users)"); + } + + public void setCoachComments(String text) { + selenium.type("ui=course::assessment_coachComment()", String.valueOf(text)); + } + + public String getCoachComment() { + return selenium.getValue("ui=course::assessment_coachComment()"); + } + + /** + * Saves changes. + * @return + */ + public AssessmentTool save() { + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + return new AssessmentTool(selenium); + } + + /** + * Close AssessmentTool and get to the courseRun. + * @return + */ + public CourseRun close() { + selenium.click("ui=course::assessment_closeAssessmentTool()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentTool.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentTool.java new file mode 100644 index 0000000000000000000000000000000000000000..6019a853d0d2716178dd0453c1290b94bdd8d79f --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/AssessmentTool.java @@ -0,0 +1,138 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import java.util.Iterator; +import java.util.Map; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the AssessmentTool page abstraction. + * + * @author Lavinia Dumitrescu + * + */ +public class AssessmentTool extends OLATSeleniumWrapper { + + + /** + * @param selenium + */ + public AssessmentTool(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=course::assessment_selectType(text=As per user)")) { + throw new IllegalStateException("This is not the - Assessment tool - page"); + } + } + + /** + * Selects "As per user" if not already selected, selects user, and selects the courseElemTitle + * to get to the AssessmentForm. + * + * @param userName + * @param courseElemTitle + * @return + */ + public AssessmentForm getAssessmentFormAsPerUser(String userName, String courseElemTitle) { + getAssessmentTableAsPerUser(userName, courseElemTitle, false); + selenium.click("ui=course::assessment_selectAssessmentCourseNode(title=" + courseElemTitle + ")"); + selenium.waitForPageToLoad("30000"); + return new AssessmentForm(selenium); + } + + public String getScoreInTableAsPerUser(String userName, String courseElemTitle, boolean reloadTable) { + getAssessmentTableAsPerUser(userName, courseElemTitle, reloadTable); + return selenium.getText("ui=course::assessment_scoreInTable(title=" + courseElemTitle + ")"); + } + + public String getPassedStatusInTableAsPerUser(String userName, String courseElemTitle, boolean reloadTable) { + getAssessmentTableAsPerUser(userName, courseElemTitle, reloadTable); + return selenium.getText("ui=course::assessment_passedStatusInTable(title=" + courseElemTitle + ")"); + } + + public String getAttemptsInTableAsPerUser(String userName, String courseElemTitle, boolean reloadTable) { + getAssessmentTableAsPerUser(userName, courseElemTitle, reloadTable); + return selenium.getText("ui=course::assessment_attemptsInTable(title=" + courseElemTitle + ")"); + } + + /** + * Go to the assessment table - via "As per user". + * @param userName + * @param courseElemTitle + * @param reloadTable - this is a workaround for an assessment tool bug. (the table doesn't update if a value changes + * on another cluster node) + */ + private void getAssessmentTableAsPerUser(String userName, String courseElemTitle, boolean reloadTable) { + if(!selenium.isElementPresent("ui=course::assessment_tableFilterForm()") || reloadTable) { + selenium.click("ui=course::assessment_selectType(text=As per user)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::assessment_selectUser(username=" + userName + ")"); + selenium.waitForPageToLoad("10000"); + } + } + + public void bulkAssessment(String courseElementTitle, Map<String,Integer> userScoreMap) { + selenium.click("ui=course::assessment_selectType(text=Bulk assessment)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::assessment_startBulkAssessment()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::assessment_selectAssessmentCourseNodeInWizard(title=" + courseElementTitle + ")"); + selenium.waitForPageToLoad("30000"); + Iterator<String> userIterator = userScoreMap.keySet().iterator(); + String userScoreString = ""; + while(userIterator.hasNext()) { + String user = userIterator.next(); + Integer score = userScoreMap.get(user); + if(userScoreString.length()>0) { + userScoreString += "\n"; + } + userScoreString += user + " " + score; + } + System.out.println("userScoreString " + userScoreString); + selenium.type("ui=course::assessment_bulkAssessmentValues()", userScoreString); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::assessment_closeBulkAssessmentWizard()"); + } + + /** + * Closes the AssessmentTool. + * @return + */ + public CourseRun close() { + selenium.click("ui=course::assessment_closeAssessmentTool()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/BlogRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/BlogRun.java new file mode 100644 index 0000000000000000000000000000000000000000..be3b43fb3fc5e9330aae525b28fc720f3cef6f38 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/BlogRun.java @@ -0,0 +1,46 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.lr.BlogResource; + +import com.thoughtworks.selenium.Selenium; + +/** + * Uses a <code>BlogResource</code> to delegate the implementation to it. + * The difference between a <code>BlogRun</code> and a <code>BlogResource</code> is that a <code>BlogRun</code> instance + * could only be constructed within a <code>CourseRun</code> whereas a <code>BlogResource</code> lives in a separate resource tab. + * + * @author lavinia + * + */ + +public class BlogRun extends OLATSeleniumWrapper { + + private BlogResource blogResource; + + public BlogRun(Selenium selenium) { + super(selenium); + + blogResource = new BlogResource(selenium,""); + } + + public void createEntry(String title, String description, String content, boolean publish) { + blogResource.createEntry(title, description, content, publish); + } + + public boolean hasDraft(String title) { + return blogResource.hasDraftEntry(title); + } + + public void editEntry(String title, String description, String content, boolean publish) { + blogResource.editEntry(title, description, content, publish); + } + + public void commentEntry(String entryTitle, String comment) { + blogResource.commentEntry(entryTitle, comment); + } + + public boolean hasComments(String entryTitle, int numComments) { + return blogResource.hasComments(entryTitle, numComments); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseElement.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseElement.java new file mode 100644 index 0000000000000000000000000000000000000000..9c389dafd5d9d49a9ff6d42c2be059f22ee5ce67 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseElement.java @@ -0,0 +1,23 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Generic course element. Provides access to the CourseRun. + * + * @author lavinia + * + */ +public class CourseElement extends OLATSeleniumWrapper{ + + public CourseElement(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public CourseRun getCourseRun() { + return new CourseRun(selenium); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseRun.java new file mode 100644 index 0000000000000000000000000000000000000000..607ccaa0d65d3f4aef1f2e235914d62a4377c523 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/CourseRun.java @@ -0,0 +1,414 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.PageLoadWait; +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.components.ChatComponent; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.group.GroupManagement; +import org.olat.test.util.selenium.olatapi.group.RightsManagement; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; + +import com.thoughtworks.selenium.Selenium; + +/** + * OLAT abstraction for the Course Run. + * @author Lavinia Dumitrescu + * + */ +public class CourseRun extends OLATSeleniumWrapper { + + + + /** + * @param selenium + */ + public CourseRun(Selenium selenium) { + super(selenium); + + try { + //delay at load course since 23.06.09 + Thread.sleep(3000); + } catch (Exception e) { + } + //Check that we're on the right place + if(!selenium.isElementPresent("ui=course::toolbox_generalTools_detailedView()")) { + throw new IllegalStateException("This is not the - Course run - page"); + } + } + + /** + * Selects root, it must start with: title. + * (Warning: the titles are truncated! if they are longer than 22 chars) + * @param title + * @return + */ + public StructureElement selectRoot(String title) { + String truncatedTitle = title; + if(title.length()>22) { + truncatedTitle = title.substring(0, 22); + } + selenium.click("ui=course::menu_root(nameOfCourse=" + truncatedTitle + ")"); + selenium.waitForPageToLoad("30000"); + return new StructureElement(selenium); + } + + /** + * Tries to select a course element than is no more visible, so it gets the root. + * @param title + * @return + */ + public StructureElement selectAnyButGetToRoot(String title) { + return selectAnyButGetToRoot(title, PageLoadWait.DEFAULT); + } + + public StructureElement selectAnyButGetToRoot(String title, PageLoadWait wait) { + selectCourseElement(title, wait); + return new StructureElement(selenium); + } + + /** + * Selects course element. CourseRun page still valid (returns void). + * Use this if the type of the selected element doesn't matter. + * @param title + */ + public void selectCourseElement(String title) { + selectCourseElement(title, PageLoadWait.DEFAULT); + } + + public void selectCourseElement(String title, PageLoadWait wait){ + selenium.click("ui=course::menu_link(link=" + title + ")"); + if(wait != PageLoadWait.NO_WAIT){ + selenium.waitForPageToLoad(wait.getMs()); + } + } + + /** + * Selects course element, identified by "position" (root's child). + * + * @param position starts from 1. + */ + public boolean selectCourseElement(int position) { + if(selenium.isElementPresent("ui=course::menu_positionedCourseElem(index=" + position + ")")) { + selenium.click("ui=course::menu_positionedCourseElem(index=" + position + ")"); + selenium.waitForPageToLoad("30000"); + return true; + } else if(position==1){ + System.out.println("NO COURSE ELEMENT FOUND TO BE SELECTED. IS THIS NOT STRANGE???"); + //throw new IllegalStateException("NO COURSE ELEMENT FOUND TO BE SELECTED! Is this really an empty course?"); + } + return false; + } + + /** + * + * @param title + * @return Returns an EnrolmentRun element. + */ + public EnrolmentRun selectEnrolment(String title) { + selectCourseElement(title); + return new EnrolmentRun(selenium); + } + + /** + * Selects the forum element with the given title. + * @param title + * @return + */ + public Forum selectForum(String title) { + selectCourseElement(title); + if(selenium.isElementPresent("ui=course::content_forum_newTopic()") || selenium.isElementPresent("ui=course::content_forum_displayForum()")) { + return new Forum(selenium); + } + throw new IllegalStateException("This is not the - Forum - page"); + } + + public TopicAssignmentRun selectTopicAssignment(String title) { + selectCourseElement(title); + //TODO: LD: add check - is this a project broker element? + return new TopicAssignmentRun(selenium); + } + + /** + * Selects and returns the SCORM element with the given title. + * @param title + * @return + */ + public SCORM selectSCORM(String title) { + selectCourseElement(title); + if(selenium.isElementPresent("ui=course::content_scorm_scormPreview()")) { + return new SCORM(selenium); + } + throw new IllegalStateException("This is not the - SCORM - page"); + } + + /** + * Selects and returns the Wiki element with the given title. + * + * @param title + * @return + */ + public WikiRun selectWiki(String title) { + //selectCourseElement(title); + //replace selectCourseElement call, no waitForPageToLoad needed + selenium.click("ui=course::menu_link(link=" + title + ")"); + try { + Thread.sleep(3000); + } catch (Exception e) { + } + if(selenium.isElementPresent("ui=wiki::sideNavigation_index()")) { + return new WikiRun(selenium); + } + throw new IllegalStateException("This is not the - Wiki - page"); + } + + /** + * Selects and returns an Assessment element with the given title. + * @param title + * @return + */ + public AssessmentElement selectAssessmentElement(String title) { + selectCourseElement(title); + return new AssessmentElement(selenium); + } + + /** + * Closes the CourseRun tab. (Leaves the CourseRun context.) + * Get to the previous selected tab + * + */ + public void close(String title) { + selenium.click("ui=tabs::closeCourse(nameOfCourse=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Selects the course tab, in case the selection changed to another tab. + * @param title + */ + public void selectCourseTab(String title) { + selenium.click("ui=tabs::selectCourse(nameOfCourse=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * It assumes that this is the only opened course. + */ + public void closeAny() { + selenium.click("ui=tabs::closeAnyCourse()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @return Returns a CourseEditor object. + */ + public CourseEditor getCourseEditor() { + selenium.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium.waitForPageToLoad("60000"); + return new CourseEditor(selenium); + } + + /** + * If the course run was disposed by another process (e.g. published, or properties modified), + * your CourseRun object gets disposed. + * @return + */ + public DisposedCourseRun getDisposedCourseRun() { + return new DisposedCourseRun(selenium); + } + + public ChatComponent getChatComponent() { + return new ChatComponent(selenium); + } + + /** + * The user tries to open the courseEditor but it is locked. + * The caller of this method expects to find the course locked, so it should not open the CourseEditor. + * + * @return Returns true if the "alreadyLocked" message shows up, false otherwise. + */ + public boolean checkCourseLocked(String lockOwnerUsername) throws Exception { + selenium.click("ui=course::toolbox_courseTools_courseEditor()"); + selenium.waitForPageToLoad("30000"); + + // and wait until 'This course is currently edited by lockOwnerUsername and therefore locked.' appears + for (int second = 0;; second++) { + if (second >= 20) return false; + try { + if (selenium.isTextPresent("This course is currently edited by "+lockOwnerUsername+" and therefore locked.")) + return true; + } catch (Exception e) {} + + Thread.sleep(1000); + } + } + + /** + * + * @return Returns a LRDetailedView object. + */ + public LRDetailedView getDetailedView() { + selenium.click("ui=course::toolbox_generalTools_detailedView()"); + selenium.waitForPageToLoad("30000"); + return new LRDetailedView(selenium); + } + + + public void setBookmark() { + selenium.click("ui=course::toolbox_generalTools_setBookmark()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + + /** + * Open group management from course run. + * @return Returns a GroupManagement object. + */ + public GroupManagement getGroupManagement() { + selenium.click("ui=course::toolbox_courseTools_groupManagement()"); + selenium.waitForPageToLoad("30000"); + return new GroupManagement(selenium); + } + + /** + * Open rights management from course run + * @return Returns a Rightsmanagement object + * + * @author Thomas Linowsky + */ + public RightsManagement getRightsManagement(){ + selenium.click("ui=course::toolbox_courseTools_rightsManagement()"); + selenium.waitForPageToLoad("30000"); + return new RightsManagement(selenium); + } + + /** + * TODO: LD: is this the right place for this method ??? + * @param groupName + * @param userName + */ + public void removeFromTutoredGroup(String groupName, String userName) { + selenium.click("ui=course::toolbox_myGroupsTools_tutoredGroups(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=group::menu_administration()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=group::content_members_tabMembers()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_participants_remove()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @param groupName + * @return + */ + public boolean hasTutoredGroup(String groupName) { + if(selenium.isElementPresent("ui=course::toolbox_myGroupsTools_tutoredGroups(nameOfGroup=" + groupName + ")")) { + return true; + } + return false; + } + + /** + * Returns true if it has a group with this groupName in "My learning groups". + * @param groupName + * @return + */ + public boolean hasMyGroup(String groupName) { + if(selenium.isElementPresent("ui=course::toolbox_myGroupsTools_myLearningGroups(nameOfGroup=" + groupName + ")")) { + return true; + } + return false; + } + + /** + * + * @return Returns an AssessmentTool instance + */ + public AssessmentTool getAssessmentTool() { + selenium.click("ui=course::toolbox_courseTools_assessmentTool()"); + selenium.waitForPageToLoad("30000"); + return new AssessmentTool(selenium); + } + + /** + * Selects a test element with the given title. + * @param title + * @return + */ + public TestElement selectTest(String title) { + selectCourseElement(title); + if(selenium.isElementPresent("ui=commons::start()") || selenium.isTextPresent("There are no more attempts at your disposal.")) { + return new TestElement(selenium); + } + throw new IllegalStateException("This is not the - Test Element - page"); + } + + public QuestionnaireElement selectQuestionnaire(String title) { + selectCourseElement(title); + return new QuestionnaireElement(selenium); + } + + public FileDialog selectFileDialog(String title) { + selectCourseElement(title); + //TODO: LD: check if this a FileDialog element!!! + return new FileDialog(selenium); + } + + public Folder selectFolder(String title) { + selectCourseElement(title); + //TODO: LD: check if this a Folder element!!! + return new Folder(selenium); + } + + public LTIRun selectLTI(String title) { + selectCourseElement(title); + return new LTIRun(selenium); + } + + public BlogRun selectBlog(String title) { + selectCourseElement(title); + return new BlogRun(selenium); + } + + public PodcastRun selectPodcast(String title) { + selectCourseElement(title); + return new PodcastRun(selenium); + } + + public InfoMessageRun selectInfoMessage(String title) { + selectCourseElement(title); + return new InfoMessageRun(selenium); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/DisposedCourseRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/DisposedCourseRun.java new file mode 100644 index 0000000000000000000000000000000000000000..05082d2320f96c725e2c945219213b7b61bf2330 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/DisposedCourseRun.java @@ -0,0 +1,35 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the disposed course run. + * One could get to this, if the course run gets disposed either by a course publish, + * or by modify course properties. + * + * @author Lavinia Dumitrescu + * + */ +public class DisposedCourseRun extends OLATSeleniumWrapper { + + public DisposedCourseRun(Selenium selenium) { + super(selenium); + + if(!selenium.isElementPresent("ui=course::disposed_closeAndRestart()")) { + //click anywhere, the course run was disposed anyway + selenium.click("ui=course::toolbox_generalTools_detailedView()"); + selenium.waitForPageToLoad("30000"); + } + } + + public CourseRun closeCourseAndRestart() { + if(selenium.isElementPresent("ui=course::disposed_closeAndRestart()")) { + selenium.click("ui=course::disposed_closeAndRestart()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + throw new IllegalStateException("There is no - Close and restart course - button present!"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/EnrolmentRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/EnrolmentRun.java new file mode 100644 index 0000000000000000000000000000000000000000..3c851586a0fa5ca405ff46633ce768bb0cb79a04 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/EnrolmentRun.java @@ -0,0 +1,66 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Enrolment course run element. + * + * @author Lavinia Dumitrescu + * + */ +public class EnrolmentRun extends OLATSeleniumWrapper { + + private final String ENROLLED = "enrolled"; + + + /** + * @param selenium + */ + public EnrolmentRun(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=course::content_enrollment_enrolmentType()") && !selenium.isElementPresent("ui=course::content_contentElement()")) { + throw new IllegalStateException("This is not the - Enrolment - page"); + } + } + + public void enrol(String groupName) { + selenium.click("ui=course::content_enrollment_enrolOnGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + } + + public void cancelEnrolment(String groupName) { + if(alreadyEnrolled(groupName)) { + selenium.click("ui=course::content_enrollment_cancelEnrolment(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + } + } + + public boolean alreadyEnrolled(String groupName) { + return ENROLLED.equals(selenium.getText("ui=course::content_enrollment_enrolledOrNot(nameOfGroup=" + groupName + ")")); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/FileDialog.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/FileDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..949f730c2cabb73821711bce98d55eec55d0ada3 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/FileDialog.java @@ -0,0 +1,42 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Represents a FileDialog course element in course run. + * + * @author lavinia + * + */ +public class FileDialog extends OLATSeleniumWrapper { + + public FileDialog(Selenium selenium) { + super(selenium); + // TODO: LD: add check - where am I? + } + + /** + * Upload file. + * @param fileName + */ + public void uploadFile(String fileName) { + selenium.click("ui=course::content_fileDialog_uploadFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=upload::fileChooser()", fileName); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * If any file present, delete it. + * If more files, use deleteFile(fileName) + */ + public void deleteSingleFile() { + selenium.click("ui=course::content_forum_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/Forum.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/Forum.java new file mode 100644 index 0000000000000000000000000000000000000000..e22d63326b7116c9900b2e5f7cbad37439cae4e4 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/Forum.java @@ -0,0 +1,238 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.portfolio.EPCollectWizard; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Forum course element run page. + * + * @author Lavinia Dumitrescu + * + */ +public class Forum extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public Forum(Selenium selenium) { + super(selenium); + + // Check that we're on the right place + if(!selenium.isElementPresent("ui=course::content_forum_newTopic()") && !selenium.isElementPresent("ui=course::content_forum_displayForum()")) { + throw new IllegalStateException("This is not the - Forum - page"); + } + } + + private void displayForumIfNecessary() { + // if Display forum visible - click on it + if(selenium.isElementPresent("ui=course::content_forum_displayForum()")) { + selenium.click("ui=course::content_forum_displayForum()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Open new forum topic with the given title and text. + * @param title + * @param body + */ + public void openNewTopic(String title, String body) { + displayForumIfNecessary(); + if(selenium.isElementPresent("ui=course::content_forum_newTopic()")) { + selenium.click("ui=course::content_forum_newTopic()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::content_forum_typeMsgTitle()"); + selenium.type("ui=course::content_forum_typeMsgTitle()", title); + //the message body shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=course::content_forum_clickMsgBody()", body); + //selenium.selectFrame("relative=top"); + selenium.click("ui=course::content_forum_save()"); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Cannot open new topic!"); + } + } + + /** + * Selects the topic with this title. + * @param title + */ + public void viewTopic(String topicTitle) { + displayForumIfNecessary(); + if(selenium.isElementPresent("ui=course::content_forum_viewTopic(nameOfTopic=" + topicTitle + ")")) { + selenium.click("ui=course::content_forum_viewTopic(nameOfTopic=" + topicTitle + ")"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Cannot viewTopic: " + topicTitle); + } + } + + + /** + * Deletes the topic with this title. + * Assumes that the Forum node is selected. + * @param title + */ + public void deleteForumTopic(String title) { + viewTopic(title); + if(selenium.isElementPresent("ui=course::content_forum_delete()")) { + selenium.click("ui=course::content_forum_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::content_forum_deleteYes()"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Cannot delete topic with this title!"); + } + } + + /** + * Replay to the topic with the topicTitle title, it assusmes that the topic contains only one message. + * @param topicTitle + * @param body + * @param replyWithQuotation + */ + public void replyToTopic(String topicTitle, String body, boolean replyWithQuotation) { + viewTopic(topicTitle); + replyToCurrentMessage(body, replyWithQuotation); + } + + /** + * It is assumed that a topic (with one message) was selected. + * @param body + * @param replyWithQuotation + */ + public void replyToCurrentMessage(String body, boolean replyWithQuotation) { + if(replyWithQuotation) { + selenium.click("ui=course::content_forum_replyWithQuotation()"); + } else { + selenium.click("ui=course::content_forum_replyWithoutQuotation()"); + } + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + selenium.waitForPageToLoad("30000"); + //the message body shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.click("ui=course::content_forum_clickMsgBody()"); + selenium.type("ui=course::content_forum_clickMsgBody()", body); + //selenium.selectFrame("relative=top"); + selenium.click("ui=course::content_forum_save()"); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + selenium.waitForPageToLoad("30000"); + } + + /** + * Assumes that a certain message in this forum is selected, so the "Edit" link is present. + * @param fileName + */ + public void attachFileToMsg(String fileName) { + editCurrentMessage(); + + selenium.type("ui=upload::fileChooser()", fileName); + selenium.waitForPageToLoad("30000"); + sleepThread(5000); + selenium.click("ui=course::content_forum_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Deletes the attached file from the current selected message, if possible, + * and saves the message. + * + */ + public void deleteAttachedFile(String fileName) { + editCurrentMessage(); + + selenium.click("ui=course::content_forum_deleteFile(nameOfFile=" + fileName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=course::content_forum_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Only one selenium step. A test case needs openNewTopic decomposed in composing steps. + */ + public void clickNewTopic() { + selenium.click("ui=course::content_forum_newTopic()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Type in a new forum message assuming that we already have an open message editor. + * Save message. + * @param title + * @param body + */ + public void typeInNewMessage(String title, String body) { + selenium.click("ui=course::content_forum_typeMsgTitle()"); + selenium.type("ui=course::content_forum_typeMsgTitle()", title); + //the message body shows up in an iframe + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=course::content_forum_clickMsgBody()", body); + //selenium.selectFrame("relative=top"); + selenium.click("ui=course::content_forum_save()"); + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + } + selenium.waitForPageToLoad("30000"); + } + + /** + * Start editing the current forum message, if "Edit" button present. + */ + private void editCurrentMessage() { + if(selenium.isElementPresent("ui=course::content_forum_edit()")) { + selenium.click("ui=course::content_forum_edit()"); + selenium.waitForPageToLoad("30000"); + } else if (!selenium.isElementPresent("ui=course::content_forum_save()")) { + throw new IllegalStateException("Edit - button not available!"); + } + } + + /** + * click the ePortfolio button to start collecting message as artefact + */ + public EPCollectWizard collectAsArtefact() { + if (selenium.isElementPresent("ui=course::content_forum_collectAsArtefact()")) { + selenium.click("ui=course::content_forum_collectAsArtefact()"); + selenium.waitForPageToLoad("30000"); + return new EPCollectWizard(selenium); + } + return null; + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/InfoMessageRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/InfoMessageRun.java new file mode 100644 index 0000000000000000000000000000000000000000..12e5fa1ffb2112728085ab3b4c1189f0d998b97e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/InfoMessageRun.java @@ -0,0 +1,149 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + + +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * Description:<br> + * + * + * <P> + * Initial Date: 4. jan 2011 <br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class InfoMessageRun extends OLATSeleniumWrapper { + + public InfoMessageRun(Selenium selenium) { + super(selenium); + } + + /* + * Create a message + */ + public void createMessage(String title, String message) { + selenium.click("ui=infoMessage::createMessage()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Subject)", title); + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Message)", message); + + selenium.click("ui=infoMessage::finishMessage()"); + selenium.waitForPageToLoad("30000"); + + try{//the order by is made up to the second, if the selenium test is too quick + //the order is not predictable. + Thread.sleep(1100); + } catch(InterruptedException ie) { + ie.printStackTrace(System.out); + } + } + + public void showOlderMessage() { + selenium.click("ui=infoMessage::olderMessage()"); + selenium.waitForPageToLoad("30000"); + } + + public void showCurrentMessage() { + selenium.click("ui=infoMessage::currentMessage()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean hasMessage(String title) { + if(selenium.isElementPresent("ui=infoMessage::messageTitle(titleOfMessage=" + title + ")")) { + return true; + } + return false; + } + + public boolean canCreateMessage() { + if(selenium.isElementPresent("ui=infoMessage::createMessage()")) { + return true; + } + return false; + } + + public boolean canEditMessage() { + if(selenium.isElementPresent("ui=infoMessage::editFirstMessage()")) { + return true; + } + return false; + } + + public boolean canDeleteMessage() { + if(selenium.isElementPresent("ui=infoMessage::deleteFirstMessage()")) { + return true; + } + return false; + } + + public void editFirstMessage() { + selenium.click("ui=infoMessage::editFirstMessage()"); + selenium.waitForPageToLoad("30000"); + } + + public void deleteFirstMessage() { + selenium.click("ui=infoMessage::deleteFirstMessage()"); + selenium.waitForPageToLoad("30000"); + } + + public void dialogOk() { + selenium.click("ui=dialog::OK()"); + } + + public void save() { + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + } + + public void yes() { + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + + public void cancel() { + selenium.click("ui=dialog::Cancel()"); + selenium.waitForPageToLoad("30000"); + } + + public void close() { + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean isMessageEdited() { + if(selenium.isElementPresent("ui=infoMessage::messageInEdition()")) { + return true; + } + return false; + } + + public boolean isMessageAlreadyEdited() { + if(selenium.isElementPresent("ui=infoMessage::messageAlreadyEdited()")) { + return true; + } + return false; + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/LTIRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/LTIRun.java new file mode 100644 index 0000000000000000000000000000000000000000..cd0197a1be72bd20760c025b1ca813b4bc437b4b --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/LTIRun.java @@ -0,0 +1,30 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Basic LTI run. + * + * @author lavinia + * + */ +public class LTIRun extends OLATSeleniumWrapper { + + public LTIRun(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public void launch() { + selenium.selectFrame("//iframe[@id='IMSBasicLTIFrame']"); + if(selenium.isElementPresent("ui=course::content_lti_launch()")) { + selenium.click("ui=course::content_lti_launch()"); + //TODO: LD: add security warning confirmation step! + } else { + throw new IllegalStateException("Cannot launch LTI, button missing!"); + } + selenium.selectFrame("relative=top"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/PodcastRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/PodcastRun.java new file mode 100644 index 0000000000000000000000000000000000000000..e5f8f68845e2ff5bac9a879bb9f0750a9690a3ac --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/PodcastRun.java @@ -0,0 +1,34 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.lr.PodcastResource; + +import com.thoughtworks.selenium.Selenium; + +public class PodcastRun extends OLATSeleniumWrapper { + + private PodcastResource podcastResource; + + public PodcastRun(Selenium selenium) { + super(selenium); + + podcastResource = new PodcastResource(selenium, ""); + } + + public void createEpisode(String title, String description, String fileName) { + podcastResource.createEpisode(title, description, fileName); + } + + public void editEpisode(String title, String description, String fileName) { + podcastResource.editEpisode(title, description, fileName); + } + + public void commentEpisode(String title,String comment) { + podcastResource.commentEpisode(title, comment); + } + + public boolean hasComments(String entryTitle, int numComments) { + return podcastResource.hasComments(entryTitle, numComments); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QTIHelper.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QTIHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..9b51a56dbdbe731653665c2ba0dab26083df3749 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QTIHelper.java @@ -0,0 +1,40 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import com.thoughtworks.selenium.Selenium; + +public class QTIHelper { + + /** + * Select the answer for the selected SingleChoice question type. + * @param answer + */ + public static void setSingleChoiceSolution (Selenium selenium, String answer) { + selenium.click("ui=qti::testItemFormElement(text=" + answer + ")"); + selenium.click("ui=qti::saveAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Select the MultipleChoice answers. + * @param answers + */ + public static void setMultipleChoiceSolution(Selenium selenium, String[] answers) { + for(String answer:answers) { + selenium.click("ui=qti::testItemFormElement(text=" + answer + ")"); + } + selenium.click("ui=qti::saveAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Fill in the answer for the given text fragment. + * TODO: LD: check if it works with more than 1 text fragments. + * @param textFragment + * @param answer + */ + public static void fillInGap(Selenium selenium, String textFragment, String answer) { + selenium.type("ui=qti::testGapItemFormElement(text=" + textFragment + ")", answer); + selenium.click("ui=qti::saveAnswer()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireElement.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireElement.java new file mode 100644 index 0000000000000000000000000000000000000000..6c652a7a0bdddc1a3746bbff1ebda28101960799 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireElement.java @@ -0,0 +1,37 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Questionnaire course element. + * + * @author Lavinia Dumitrescu + * + */ +public class QuestionnaireElement extends OLATSeleniumWrapper { + + public QuestionnaireElement(Selenium selenium) { + super(selenium); + // TODO : LD: add check: where am I? + } + + /** + * A questionnaire could be started only once! + * @return + */ + public QuestionnaireRun start() { + if(selenium.isElementPresent("ui=commons::start()")) { + selenium.click("ui=commons::start()"); + selenium.waitForPageToLoad("30000"); + return new QuestionnaireRun(selenium); + } else { + throw new IllegalStateException("Cannot start questionnaire!"); + } + } + + public boolean cannotStartAnymore() { + return !selenium.isElementPresent("ui=commons::start()"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireRun.java new file mode 100644 index 0000000000000000000000000000000000000000..3b87c12a5381118bb0c49e3f8b817442be9318de --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/QuestionnaireRun.java @@ -0,0 +1,110 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the questionnaire run page. + * + * @author Lavinia Dumitrescu + * + */ +public class QuestionnaireRun extends OLATSeleniumWrapper { + + public QuestionnaireRun(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + /** + * Press finishQuestionnaire, you cannot start the questionnaire a second time. + */ + public CourseRun finish() { + selenium.click("ui=qti::finishQuestionnaire()"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.getConfirmation().matches("^Do you really want to submit[\\s\\S]$")); + return new CourseRun(selenium); + } + + /** + * Press cancel and close, and get to the QuestionnaireElement. + */ + public QuestionnaireElement cancel() { + selenium.click("ui=qti::cancelQuestionnaire()"); + selenium.waitForPageToLoad("30000"); + + selenium.click("ui=qti::closeTest()"); + selenium.waitForPageToLoad("30000"); + return new QuestionnaireElement(selenium); + } + + /** + * Press suspend and get to the QuestionnaireElement. + * @return + */ + public QuestionnaireElement suspend() { + selenium.click("ui=qti::suspendQuestionnaire()"); + selenium.waitForPageToLoad("30000"); + + return new QuestionnaireElement(selenium); + } + + /** + * Selects the menu item with the given name. + * @param title + */ + public void selectMenuItem(String title) { + selenium.click("ui=qti::menuItem(titleOfItem=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + + public boolean isSuspendPresent() { + return selenium.isElementPresent("ui=qti::suspendQuestionnaire()"); + } + + public boolean isCancelPresent() { + return selenium.isElementPresent("ui=qti::cancelQuestionnaire()"); + } + + /** + * Select the answer for the selected SingleChoice question type. + * @param answer + */ + public void setSingleChoiceSolution (String answer) { + QTIHelper.setSingleChoiceSolution(selenium, answer); + } + + /** + * Select the MultipleChoice answers. + * @param answers + */ + public void setMultipleChoiceSolution(String[] answers) { + QTIHelper.setMultipleChoiceSolution(selenium, answers); + } + + /** + * Fill in the answer for the given text fragment. + * TODO: LD: check if it works with more than 1 text fragments. + * @param textFragment + * @param answer + */ + public void fillInGap(String textFragment, String answer) { + QTIHelper.fillInGap(selenium, textFragment, answer); + } + + /** + * Fill in the essay text area. + * @param text + */ + public void fillInEssay (String text) { + selenium.type("ui=qti::questionnaireEssayTextArea()", text); + selenium.click("ui=qti::saveAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + public void next() { + selenium.click("ui=qti::next()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/SCORM.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/SCORM.java new file mode 100644 index 0000000000000000000000000000000000000000..bbab6d06d11da80b19e374b74693470b3dce172c --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/SCORM.java @@ -0,0 +1,58 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the SCORM run page. + * @author Lavinia Dumitrescu + * + */ +public class SCORM extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public SCORM(Selenium selenium) { + super(selenium); + + // Check that we're on the right place + if(!selenium.isElementPresent("ui=course::content_scorm_scormPreview()")) { + throw new IllegalStateException("This is not the - SCORM run - page"); + } + } + + public void showSCORMLearningContent() { + selenium.click("ui=course::content_scorm_scormPreview()"); + selenium.waitForPageToLoad("30000"); + } + + public CourseRun back() throws Exception { + selenium.click("ui=course::content_scorm_back()"); + Thread.sleep(500); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/StructureElement.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/StructureElement.java new file mode 100644 index 0000000000000000000000000000000000000000..4c6793733d7962ce50c85918ae5a04b097310137 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/StructureElement.java @@ -0,0 +1,46 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Structure course run element. + * @author Lavinia Dumitrescu + * + */ +public class StructureElement extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public StructureElement(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public String getPassedStatus() { + return selenium.getText("ui=course::content_passedFailedStatus()"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestElement.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestElement.java new file mode 100644 index 0000000000000000000000000000000000000000..c9719b11780a2f1ae9182883a81511e59d1c01ec --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestElement.java @@ -0,0 +1,90 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Test course run element. + * @author Lavinia Dumitrescu + * + */ +public class TestElement extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public TestElement(Selenium selenium) { + super(selenium); + // TODO : LD: add check: where am I? + } + + /** + * Starts the current selected test. + * @return a TestRun instance. + */ + public TestRun startTest() { + if(selenium.isElementPresent("ui=commons::start()")) { + selenium.click("ui=commons::start()"); + selenium.waitForPageToLoad("30000"); + return new TestRun(selenium); + } else { + throw new IllegalStateException("This is not a test element - cannot start test!"); + } + } + + public boolean cannotStartTestAnymore() { + return !selenium.isElementPresent("ui=commons::start()"); + } + + /** + * + * @return the achieved score, if any, throws IllegalStateException otherwise. + */ + public String getAchievedScore() { + if(selenium.isElementPresent("ui=qti::yourScore()")) { + return selenium.getText("ui=qti::yourScore()"); + } + throw new IllegalStateException("There is no score information to be displayed yet."); + } + + public String getStatus() { + if(selenium.isElementPresent("ui=qti::yourStatus()")) { + return selenium.getText("ui=qti::yourStatus()"); + } + throw new IllegalStateException("There is no status information to be displayed yet."); + } + + public boolean isShowResultsPresent() { + return selenium.isElementPresent("ui=qti::showHideResults(text=Show results)"); + } + + public String getCommentFromTutor() { + if(selenium.isElementPresent("ui=qti::commentFromTutor()")) { + return selenium.getText("ui=qti::commentFromTutor()"); + } + System.out.println("No comment found"); + return ""; + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestRun.java new file mode 100644 index 0000000000000000000000000000000000000000..8fa4417e4172ab0b1f635ba5773eb5b49445354f --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TestRun.java @@ -0,0 +1,197 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import java.util.Iterator; +import java.util.Map; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the TestRun page. + * + * @author Lavinia Dumitrescu + * + */ +public class TestRun extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public TestRun(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=qti::finishTest()")) { + throw new IllegalStateException("This is not the - Test run - page"); + } + } + + /** + * Finish and close this test. + * @return Returns a CourseRun instance. + * @throws Exception + */ + public TestElement finishTest(boolean assertAchievedScore, int referenceScore) throws Exception { + selenium.click("ui=qti::finishTest()"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.getConfirmation().matches("^Do you really want to submit[\\s\\S]$")); + //check if results were saved + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + if (selenium.isTextPresent("Your results were saved")) break; + Thread.sleep(1000); + } + //check the score + if(assertAchievedScore) { + assertEquals(String.valueOf(referenceScore),selenium.getText("ui=qti::achievedScore()")); + } + //close test + selenium.click("ui=qti::closeTest()"); + selenium.waitForPageToLoad("30000"); + return new TestElement(selenium); + } + + /** + * Waits for confirmation: your results were saved, and closes test. + * The self test finishes silently, no explicit finish test command needed. + * @throws Exception + */ + public TestElement selfTestFinishedConfirm() throws Exception { + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent("Your results were saved.")) break; } catch (Exception e) {} + Thread.sleep(1000); + } + selenium.click("ui=qti::closeTest()"); + selenium.waitForPageToLoad("30000"); + return new TestElement(selenium); + } + + /*public TestElement closeTest() { + selenium.click("ui=qti::closeTest()"); + selenium.waitForPageToLoad("30000"); + return new TestElement(selenium); + }*/ + + /** + * + * @return + */ + public CourseRun suspendTest() { + if(!isSuspendPresent()) { + throw new IllegalStateException("No suspend test button available!"); + } + selenium.click("ui=qti::suspendTest()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: confirm suspend + return new CourseRun(selenium); + } + + /** + * + * @return + */ + public CourseRun cancelTest() { + if(!isCancelPresent()) { + throw new IllegalStateException("No cancel test button available!"); + } + selenium.click("ui=qti::cancelTest()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: confirm cancel + selenium.click("ui=qti::closeTest()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + + public boolean isSuspendPresent() { + return selenium.isElementPresent("ui=qti::suspendTest()"); + } + + public boolean isCancelPresent() { + return selenium.isElementPresent("ui=qti::cancelTest()"); + } + + public void next() { + selenium.click("ui=qti::next()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Fill in the answer for the given text fragment. + * TODO: LD: check if it works with more than 1 text fragments. + * @param textFragment + * @param answer + */ + public void fillInGap(String textFragment, String answer) { + QTIHelper.fillInGap(selenium, textFragment, answer); + } + + /** + * Select in the KPrim answers. + * The input map contains as keys the answer text and as value a Boolean for correct or not. + * + * @param answerToCorrectMap + */ + public void setKprimSolution(Map<String, Boolean> answerToCorrectMap) { + Iterator<String> keyIterator = answerToCorrectMap.keySet().iterator(); + while(keyIterator.hasNext()) { + String currentAnswer = keyIterator.next(); + Boolean isCorrect = answerToCorrectMap.get(currentAnswer); + if(isCorrect) { + selenium.click("ui=qti::testKprimItemFormElementPlus(text=" + currentAnswer + ")"); + } else { + selenium.click("ui=qti::testKprimItemFormElementMinus(text=" + currentAnswer + ")"); + } + } + selenium.click("ui=qti::saveAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Select the MultipleChoice answers. + * @param answers + */ + public void setMultipleChoiceSolution(String[] answers) { + QTIHelper.setMultipleChoiceSolution(selenium, answers); + } + + /** + * Select the answer for the selected SingleChoice question type. + * @param answer + */ + public void setSingleChoiceSolution (String answer) { + QTIHelper.setSingleChoiceSolution(selenium, answer); + } + + /** + * Selects the menu item with the given name. + * @param title + */ + public void selectMenuItem(String title) { + selenium.click("ui=qti::menuItem(titleOfItem=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicAssignmentRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicAssignmentRun.java new file mode 100644 index 0000000000000000000000000000000000000000..acb91f240ed508be6dd408ac89b261d009aa37ed --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicAssignmentRun.java @@ -0,0 +1,193 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Represents a TopicAssignment course element in course run. + * + * @author lavinia + * + */ +public class TopicAssignmentRun extends CourseElement { + + public TopicAssignmentRun(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + /** + * + * @param title + * @param description + * @param limitVacancies + * @param vacanciesNumber + * @return + */ + public TopicEditor createTopic(String title, String description, boolean limitVacancies, int vacanciesNumber) { + selenium.click("ui=projectBroker::createTopic()"); + selenium.waitForPageToLoad("30000"); + if(title!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + } + if(description!=null) { + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Description)", description); + } + + //add limit vacancies, attach file, select email notification + selenium.click("ui=projectBroker::doLimitVacancies()"); + selenium.waitForPageToLoad("30000"); + if(vacanciesNumber>1) { + //change limit + selenium.type("ui=projectBroker::vacanciesNumber()", String.valueOf(vacanciesNumber)); + } + + //save + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + + return new TopicEditor(selenium); + } + + /** + * Accepts null as input params. If a parameter is null, do not change the defaults. + * @param title + * @param description + * @param faculty + * @param registrationStartDate + * @param registrationEndDate + * @param dueStartDate + * @param dueEndDate + * @param limitVacancies + * @param vacanciesNumber + * @param attachment + * @param emailNotification + * @return + */ + @Deprecated + public TopicEditor createTopic(String title, String description, String faculty, + String registrationStartDate, String registrationEndDate, String dueStartDate, String dueEndDate, + boolean limitVacancies, int vacanciesNumber, String attachment, boolean emailNotification) { + + selenium.click("ui=projectBroker::createTopic()"); + selenium.waitForPageToLoad("30000"); + if(title!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + } + if(description!=null) { + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Description)", description); + } + + //TODO: LD choose faculty + + //add registration start and end date + //WARNING: NO DATE CORRECTNESS CHECK IS PERFORMED! + if(registrationStartDate!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Registration)", registrationStartDate); + } + if(registrationEndDate!=null) { + selenium.type("ui=projectBroker::registrationDeadline()",registrationEndDate); + } + //add due date starting and end date + if(dueStartDate!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Due date)", dueStartDate); + } + if(dueEndDate!=null) { + selenium.type("ui=projectBroker::dueDeadline()",dueEndDate); + } + + //TODO: LD: add limit vacancies, attach file, select email notification + + //save + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + + return new TopicEditor(selenium); + } + + public boolean hasTopic(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::topicLink(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public TopicEditor openTopic(String topicName) { + selenium.click("ui=projectBroker::topicLink(nameOfTopic=" + topicName + ")"); + selenium.waitForPageToLoad("30000"); + return new TopicEditor(selenium); + } + + public boolean hasVacancies(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::hasVacancies(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean isFilled(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::filled(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean isTemporaryRegisterd(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::temporaryRegistration(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean isRegistered(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::isRegistered(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean hasParticipantsAccepted(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::participantsAccepted(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean hasCheckParticipants(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::checkParticipants(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean canSelectTopic(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::selectTopic(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public void selectTopic(String topicName) { + selenium.click("ui=projectBroker::selectTopic(nameOfTopic=" + topicName + ")"); + selenium.waitForPageToLoad("30000"); + } + + public boolean canDeselect(String topicName) { + if(selenium.isElementPresent("ui=projectBroker::deselectTopic(nameOfTopic=" + topicName + ")")) { + return true; + } + return false; + } + + public boolean canCreateTopic() { + if(selenium.isElementPresent("ui=projectBroker::createTopic()")) { + return true; + } + return false; + } + + public boolean hasTutoredGroup(String groupName) { + return getCourseRun().hasTutoredGroup(groupName); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..ac352f05c539c51df60f5ef171610ead3c327404 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/TopicEditor.java @@ -0,0 +1,217 @@ +package org.olat.test.util.selenium.olatapi.course.run; + +import java.util.List; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Topic editor, this is role independent. See the javadoc for role specific info. + * + * @author lavinia + * + */ +public class TopicEditor extends OLATSeleniumWrapper { + + public TopicEditor(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + public TopicAssignmentRun back() { + selenium.click("ui=commons::backLink()"); + selenium.waitForPageToLoad("30000"); + return new TopicAssignmentRun(selenium); + } + + private void selectFolderTab() { + if(selenium.isElementPresent("ui=projectBroker::folder_folderTab()")) { + selenium.click("ui=projectBroker::folder_folderTab()"); + selenium.waitForPageToLoad("30000"); + } + } + + public boolean hasDropbox() { + selectFolderTab(); + if (selenium.isElementPresent("ui=projectBroker::folder_dropboxDiv()")) { + return true; + } + return false; + } + + public boolean hasFileInDropBoxFolder(String folderName, String fileName) { + selectFolderTab(); + //if it has folder, select it + if (selenium.isElementPresent("ui=projectBroker::folder_dropBoxFolderLink(folderName=" + folderName + ")")) { + selenium.click("ui=projectBroker::folder_dropBoxFolderLink(folderName=" + folderName + ")"); + selenium.waitForPageToLoad("30000"); + } + //it has file + if(selenium.isElementPresent("ui=projectBroker::folder_dropBoxFolderLink(folderName=" + fileName + ")")) { + return true; + } + return false; + } + + /** + * For students. + * @param fileName + */ + public void uploadFileInDropBox(String remoteFileName) { + selectFolderTab(); + selenium.click("ui=projectBroker::folder_uploadFile()"); + selenium.waitForPageToLoad("90000"); + selenium.click("ui=projectBroker::folder_uploadFileInOverlay()"); + selenium.waitForPageToLoad("90000"); + selenium.type("ui=upload::fileChooser()", remoteFileName); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + + public boolean hasReturnbox() { + selectFolderTab(); + if (selenium.isElementPresent("ui=projectBroker::folder_returnboxDiv()")) { + return true; + } + return false; + } + + public boolean hasReturnboxFolder(String folderName) { + selectFolderTab(); + //if (selenium.isElementPresent("ui=projectBroker::folder_returnboxFolderCheckbox(folderName=" + folderName + ")")) { + if (selenium.isElementPresent("ui=projectBroker::folder_returnBoxFolderLink(folderName=" + folderName + ")")) { + return true; + } + return false; + } + + public boolean hasFileInReturnBoxFolder(String fileName) { + selectFolderTab(); + //it has file + if(selenium.isElementPresent("ui=projectBroker::folder_returnBoxFolderLink(folderName=" + fileName + ")")) { + return true; + } + return false; + } + + + /** + * Accessible only for tutors. + */ + private void edit() { + + } + + + /** + * Accessible only for tutors. + * @return + */ + public TopicAssignmentRun delete() { + selenium.click("ui=projectBroker::createTopic()"); + selenium.waitForPageToLoad("30000"); + return new TopicAssignmentRun(selenium); + } + + + /** + * Accessible only for tutors. + */ + private void createDocument(String name) { + + } + + + /** + * Accessible only for tutors. + * TODO: check if could use Folder.java + * @param filename + * @param title + * @param description + */ + public void uploadFileInReturnBoxFolder(String folderName, String remoteFileName) { + selectFolderTab(); + //select folder + selenium.click("ui=projectBroker::folder_returnBoxFolderLink(folderName=" + folderName + ")"); + selenium.waitForPageToLoad("30000"); + //upload file in the current folder + selenium.click("ui=briefCase::uploadFile()"); + selenium.waitForPageToLoad("90000"); + selenium.type("ui=upload::fileChooser()", remoteFileName); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Accessible only for tutors. + * @param name + */ + private void createFolder(String name) { + + } + + public boolean hasAdminTab() { + if(selenium.isElementPresent("ui=projectBroker::administrationOfParticipants_adminTab()")) { + return true; + } + return false; + } + + private void selectAminTab() { + if(selenium.isElementPresent("ui=projectBroker::administrationOfParticipants_adminTab()")) { + selenium.click("ui=projectBroker::administrationOfParticipants_adminTab()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Accessible only for tutors. + * @param userList + */ + private void addParticipants(List<String> userList) { + + } + + public boolean hasParticipant(String username) { + selectAminTab(); + if(selenium.isElementPresent("ui=projectBroker::administrationOfParticipants_participants_checkUser(userName=" + username + ")")) { + return true; + } + return false; + } + + + public boolean hasCandidate(String username) { + selectAminTab(); + if(selenium.isElementPresent("ui=projectBroker::administrationOfParticipants_candidates_checkUser(userName=" + username + ")")) { + return true; + } + return false; + } + + public void moveAsParticipant(String username) { + selectAminTab(); + if(selenium.isElementPresent("ui=projectBroker::administrationOfParticipants_candidates_checkUser(userName=" + username + ")")) { + selenium.click("ui=projectBroker::administrationOfParticipants_candidates_checkUser(userName=" + username + ")"); + selenium.click("ui=projectBroker::administrationOfParticipants_candidates_moveToParticipants()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("No participant with this username found!"); + } + } + + /** + * Accessible only for tutors. + * @param userList + */ + private void addAuthors(List<String> userList) { + + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/course/run/WikiRun.java b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/WikiRun.java new file mode 100644 index 0000000000000000000000000000000000000000..141f182bd6c444570377ea9fff71e5a3a66f4883 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/course/run/WikiRun.java @@ -0,0 +1,193 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.course.run; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the Wiki course Run element. + * @author Lavinia Dumitrescu + * + */ +public class WikiRun extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public WikiRun(Selenium selenium) { + super(selenium); + // Check that we're on the right place + //if(!selenium.isTextPresent("Article")) { + if(!selenium.isElementPresent("ui=wiki::sideNavigation_index()")) { + throw new IllegalStateException("This is not the - Wiki - page"); + } + } + + /** + * Edit page, save, and go to Article link. + * @param text + */ + public void editPage(String text) { + openEditor(); + selenium.click("ui=wiki::edit_editFormTextarea()"); + selenium.type("ui=wiki::edit_editFormTextarea()", text); + selenium.click("ui=commons::flexiForm_saveButton()"); //this should clean the cache + //selenium.waitForPageToLoad("30000"); + selenium.click("ui=wiki::topNavigation_article()"); //release lock + //selenium.waitForPageToLoad("30000"); + } + + public void openEditor() { + if(selenium.isElementPresent("ui=wiki::topNavigation_editPage()")) { + selenium.click("ui=wiki::topNavigation_editPage()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * + * @param filepath + * @param mediaLabel + * @throws Exception + */ + public void insertMedia(String filepath, String mediaLabel) throws Exception { + openEditor(); + if(selenium.isElementPresent("ui=wiki::edit_uploadFileButton()")) { + selenium.click("ui=wiki::edit_uploadFileButton()"); + Thread.sleep(1000); + selenium.type("ui=upload::fileChooser()", filepath); + selenium.click("ui=upload::submit()"); + //selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(3000); + } catch (Exception e) { + } + selenium.select("mediaFileChooser", "label=" + mediaLabel); + selenium.click("ui=wiki::edit_insertFileButton()"); + selenium.click("ui=commons::save()"); + //selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(3000); + } catch (Exception e) { + } + selenium.click("ui=wiki::topNavigation_article()"); + selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Upload file - link not available"); + } + } + + /** + * Creates a wiki page via the Create article, or searches a wiki page, if already selected. + * @param wikiPage + * @param articleText, could be null if search is wanted. + */ + public void createOrSearchArticle(String wikiPage, String articleText) { + //searches wikiPage and creates it if not already created + selenium.type("ui=wiki::sideNavigation_createInput()", wikiPage); + selenium.click("ui=wiki::sideNavigation_createButton()"); + selenium.waitForPageToLoad("30000"); + //new page created, edit it + if(selenium.isElementPresent("ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=" + wikiPage + ")")) { + selenium.click("ui=wiki::sideNavigation_clickAWikiPage(nameOfWikiPage=" + wikiPage + ")"); + //selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(3000); + } catch (Exception e) { + } + selenium.type("ui=wiki::edit_editFormTextarea()", articleText); + selenium.click("ui=commons::save()"); + //selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(3000); + } catch (Exception e) { + } + } else { + System.out.println("The wiki page is supposed to already exist!"); + } + } + + /** + * Searches article with this title. + * @param wikiPage + */ + public void searchArticle(String wikiPage) { + selenium.type("ui=wiki::sideNavigation_searchInput()", wikiPage); + selenium.click("ui=wiki::sideNavigation_searchButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Selects Article link. + * + */ + public void showArticle() { + selenium.click("ui=wiki::topNavigation_article()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Selects index. + * + */ + public void selectIndex() { + selenium.click("ui=wiki::sideNavigation_index()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Click the From a-z link. + * + */ + public void selectFromAToZ() { + selenium.click("ui=wiki::sideNavigation_from-a-z()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Edit menu and go to the Article link. + * @param wikiString + */ + public void editMenu(String wikiString) { + selenium.click("ui=wiki::sideNavigation_editWikiMenu()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=wiki::edit_editFormTextarea()", wikiString); + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=wiki::topNavigation_article()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Show versions and click on version compare link. + * + */ + public void showVersionsAndCompare() { + selenium.click("ui=wiki::topNavigation_versions()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=wiki::versions_compare()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/folder/Folder.java b/src/test/java/org/olat/test/util/selenium/olatapi/folder/Folder.java new file mode 100644 index 0000000000000000000000000000000000000000..501a3745b8755de126385a65c401cd00b08ce937 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/folder/Folder.java @@ -0,0 +1,331 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.folder; + +import java.util.Iterator; +import java.util.List; + +import org.olat.test.util.selenium.SeleniumHelper; +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; + +import com.mchange.util.AssertException; +import com.thoughtworks.selenium.Selenium; + +/** + * Generic Folder abstraction for the FolderRunController. + * Supposed to be used from: Personal folder, Storage folder in course editor, Folder node in course run, etc. + * + * @author Lavinia Dumitrescu + * + */ +public class Folder extends OLATSeleniumWrapper { + + public Folder(Selenium selenium) { + super(selenium); + //Check that we're on the right place + if(!selenium.isElementPresent("ui=briefCase::folderComponent()")) { + throw new IllegalStateException("This is not the - Folder - page"); + } + } + + /** + * Select item. + * @param name + */ + public void selectFileOrFolder(String name) { + if(name!=null && selenium.isElementPresent("ui=briefCase::clickBriefcaseEntry(linkText=" + name + ")")) { + selenium.click("ui=briefCase::clickBriefcaseEntry(linkText=" + name + ")"); + selenium.waitForPageToLoad("30000"); + } + } + + public void selectLink(String link, boolean waitForPageToLoad) { + selenium.click("ui=briefCase::clickBriefcaseEntry(linkText=" + link + ")"); + if(waitForPageToLoad) { + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Click on checkbox of an item. + * @param name + */ + public void checkFileOrFolder(String name) { + SeleniumHelper.safeWait(100); + if(name!=null && selenium.isElementPresent("ui=briefCase::selectBriefcaseCheckBox(linkText=" + name + ")")) { + selenium.click("ui=briefCase::selectBriefcaseCheckBox(linkText=" + name + ")"); + } + } + + /** + * Closes storage folder. + * @return + */ + public CourseEditor closeStorageFolder() { + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + return new CourseEditor(selenium); + } + + + /** + * Creates a file with a given name in the current container. + * It checks if the filename is valid and returns true if valid, false otherwise. + * Closes the overlay. + * @param fileName + */ + public boolean createFile(String folder, String fileName, String text) { + selectFileOrFolder(folder); + + selenium.click("ui=briefCase::createFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=briefCase::createFileName()", fileName); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Create document)"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=commons::flexiForm_formErrorMsg()")) { + selenium.click("ui=commons::flexiForm_cancelButton()"); + selenium.waitForPageToLoad("30000"); + return false; + } + //selenium.type(locator, text) + //TODO: LD: add text + if(fileName.endsWith(".txt")) { + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Content of document)", text); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } else if (fileName.endsWith(".html")) { + selenium.click("ui=briefCase::htmlEditorSaveAndClose()"); + selenium.waitForPageToLoad("30000"); + } + return true; + } + + /** + * Creates a folder if does not encounter a error message: either because the folder already exists, + * or because the folder name is invalid. + * @param folderName + * @return Returns true if folder successful created, false otherwise. + */ + public boolean createFolder(String folderName) { + selenium.click("ui=briefCase::createFolder()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Name)", folderName); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Create folder)"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=commons::flexiForm_formErrorMsg()")) { + selenium.click("ui=commons::flexiForm_cancelButton()"); + return false; + } + return true; + } + + /** + * Uploads a file in the specified folder, or in the current folder if none specified. + * @param folder could be null. + * @param fileName + */ + public void uploadFile(String folder,String fileName) { + selectFileOrFolder(folder); + + boolean uploadIsThere = false; + int retries = 5; + while(!uploadIsThere && retries > 1){ + selenium.click("ui=briefCase::uploadFile()"); + selenium.waitForPageToLoad("90000"); + uploadIsThere = selenium.isElementPresent("ui=upload::fileChooser()"); + if(!uploadIsThere){ + retries--; + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + selenium.type("ui=upload::fileChooser()", fileName); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + + /** + * Upload, overwrite or rename. + * @param folder + * @param fileName + * @param overwrite + */ + public boolean uploadWithOverwrite(String folder,String fileName, boolean overwrite) { + selectFileOrFolder(folder); + + boolean overwritten = false; + + selenium.click("ui=briefCase::uploadFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=upload::fileChooser()", fileName); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("30000"); + if(overwrite && selenium.isTextPresent("Overwrite")) { + selenium.click("ui=commons::anyLink(linkText=Overwrite)"); + overwritten = true; + } else if(!overwrite && selenium.isTextPresent("Overwrite")) { + //TODO: LD: implement this! + } + selenium.waitForPageToLoad("30000"); + return overwritten; + } + + /** + * Delete the item with the input title. + * @param title + */ + public void deleteItem(String title) { + if(selenium.isElementPresent("ui=briefCase::selectBriefcaseCheckBox(linkText=" + title + ")")) { + selenium.click("ui=briefCase::selectBriefcaseCheckBox(linkText=" + title + ")"); + selenium.click("ui=briefCase::buttonDelete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Item deleted: " + title); + } else { + System.out.println("No item found for deletion: " + title); + } + } + + public void deleteSelection() { + if(selenium.isElementPresent("ui=briefCase::buttonDelete()")) { + selenium.click("ui=briefCase::buttonDelete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Selection deleted"); + } else { + System.out.println("No item deleted."); + } + } + + public void moveSelection(List selection) { + + } + + public void copySelection(List selection) { + + } + + /** + * Return true if successfully zipped. + * @param selection + * @param zipName + * @return + */ + public boolean zipSelection(List<String> selection, String zipName) { + Iterator<String> selIterator = selection.iterator(); + while(selIterator.hasNext()) { + String item = selIterator.next(); + checkFileOrFolder(item); + } + //buttonZip + selenium.click("ui=briefCase::buttonZip()"); + selenium.waitForPageToLoad("30000"); + //enter zip name + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Name of new Zip file)", zipName); + + selenium.click("ui=briefCase::zipFiles()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=briefCase::zipFiles()")) { + //todo: cancel + return false; + } + return true; + } + + /** + * Cancels zip workflow if any started. + */ + public void cancelZipSelection() { + if(selenium.isElementPresent("ui=briefCase::zipFiles()")) { + selenium.click("ui=commons::flexiForm_cancelButton()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void unzipSelection(List selection) { + + } + + /** + * + * @param fileFolderName + * @param newName + * @param title + * @param description + */ + public void editMetadata(String fileFolderName, String newName, String title, String description) { + selenium.click("ui=briefCase::editMetadata(linkText=" + fileFolderName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=File name)", newName); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + //TODO: add description + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + public void editTxtFile(String fileName, String content) { + selenium.click("ui=briefCase::editFile(linkText=" + fileName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Content of document)", content); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + public String getText(String fileName) { + selenium.click("ui=briefCase::editFile(linkText=" + fileName + ")"); + selenium.waitForPageToLoad("30000"); + String content = selenium.getValue("ui=commons::flexiForm_labeledTextArea(formElementLabel=Content of document)"); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + return content; + } + + public void editHtmlFile(String fileName, String content) { + + } + + public void selectAll() { + if(selenium.isElementPresent("ui=briefCase::selectAll()")) { + selenium.click("ui=briefCase::selectAll()"); + } + } + + public void deselectAll() { + + } + + public boolean isFileOrFolderPresent(String fileName) { + return selenium.isElementPresent("ui=briefCase::clickBriefcaseEntry(linkText=" + fileName + ")"); + } + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/Group.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/Group.java new file mode 100644 index 0000000000000000000000000000000000000000..7fa7de53aba78e7dab394c83094e87c1a838969d --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/Group.java @@ -0,0 +1,140 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.components.ChatComponent; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.Forum; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Lavinia Dumitrescu + * + */ +public class Group extends OLATSeleniumWrapper { + + private String groupName; + + /** + * @param selenium + */ + public Group(Selenium selenium, String groupName) { + super(selenium); + this.groupName = groupName; + try { + //delay at load group since 30.08.09 + Thread.sleep(10000); + } catch (Exception e) { + } + //Check that we're on the right place + if(!selenium.isTextPresent(groupName)) { + throw new IllegalStateException("This is not the - Group - page"); + } + } + + /** + * TODO: LD: check this out!!! + * Use carefully this method. + * This starts a course if the group was achieved via the My groups portlet, + * else if the group was achieved via the GroupManager, this doesn't return + * a CourseRun. + * <p> + * It is assumed that there is only one course associated with this group. + * + * @return Returns a CourseRun instance. + */ + public CourseRun startCourse() { + selenium.click("ui=group::menu_course()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=group::content_startCourse()"); + selenium.waitForPageToLoad("30000"); + if(!selenium.isTextPresent("General")) { + throw new IllegalStateException("This is not the - CourseRun - page, this Group was not selected via the My groups portlet"); + } + return new CourseRun(selenium); + } + + public void selectInfo() { + selenium.click("ui=group::menu_information()"); + selenium.waitForPageToLoad("30000"); + } + + public void selectCalendar() { + selenium.click("ui=group::menu_calendar()"); + selenium.waitForPageToLoad("30000"); + } + + public void selectMembers() { + selenium.click("ui=group::menu_members()"); + selenium.waitForPageToLoad("30000"); + } + + public Forum selectForum() { + selenium.click("ui=group::menu_forum()"); + selenium.waitForPageToLoad("30000"); + return new Forum(selenium); + } + + public void selectEmail() { + selenium.click("ui=group::menu_email()"); + selenium.waitForPageToLoad("30000"); + } + + public void selectFolder() { + selenium.click("ui=group::menu_folder()"); + selenium.waitForPageToLoad("30000"); + } + + public void selectWiki() { + selenium.click("ui=group::menu_wiki()"); + //outcommented selenium.waitForPageToLoad on 28.04.2010 to avoid getting the "Translation Issue encountered!" error + selenium.waitForPageToLoad("30000"); + } + + public boolean hasWiki() { + return selenium.isElementPresent("ui=group::menu_wiki()"); + } + + public GroupAdmin selectAdministration() { + selenium.click("ui=group::menu_administration()"); + selenium.waitForPageToLoad("30000"); + return new GroupAdmin(selenium); + } + + public ChatComponent selectChat() { + selenium.click("ui=group::menu_chat()"); + selenium.waitForPageToLoad("30000"); + return new ChatComponent(selenium); + } + + public void close(String groupName) { + if(selenium.isElementPresent("ui=tabs::closeGroup(nameOfGroup=" + groupName + ")")) { + selenium.click("ui=tabs::closeGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + } else { + System.out.println("Could not close this group!"); + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupAdmin.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupAdmin.java new file mode 100644 index 0000000000000000000000000000000000000000..8725da663a50303a742efd623b434db54a4fae7e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupAdmin.java @@ -0,0 +1,414 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the GroupAdministration page. + * + * @author Lavinia Dumitrescu + * + */ +public class GroupAdmin extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public GroupAdmin(Selenium selenium) { + super(selenium); + sleepThread(3000); + //Check that we're on the right place + if(!selenium.isElementPresent("ui=group::content_tools_tabTools()")) { + throw new IllegalStateException("This is not the - Administration group - page"); + } + } + + /** + * Adds participants and owners to the current group, looping through Add user(s). + * @param participants + * @param owners + * @throws Exception + */ + public void addMembers(String[] participants, String[] owners) throws Exception { + selectMembersTab(); + + //add participants + for(String userName:participants) { + selenium.click("ui=commons::usertable_participants_addUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + Thread.sleep(5000); + if(selenium.isElementPresent("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")")) { + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } else { + System.out.println("GroupAdmin.addMembers - since no user found, skip participant: " + userName); + } + } + //add owners + for(String userName:owners) { + selenium.click("ui=commons::usertable_owners_addUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Import participants to this group. Accepts a formatted input string, one username per row. + * Assumes that there is at least a new user in the participants list + * @param participants + */ + public boolean importParticipants(String participants) { + selectMembersTab(); + if(participants==null || participants.trim().equals("")) { + throw new IllegalArgumentException("participants string is not valid!"); + } + + selenium.click("ui=commons::usertable_participants_import()"); + selenium.waitForPageToLoad("30000"); + //wizard + //step 1: enter username and press next + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=User names)", participants); + sleepThread(3000); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + //selenium.waitForPageToLoad("30000"); + sleepThread(3000); + //step2: suppose they are all new users + if(selenium.isElementPresent("ui=commons::anyLink(linkText=Next)")) { + selenium.click("ui=commons::anyLink(linkText=Next)"); + selenium.waitForPageToLoad("30000"); + //step 3: do not sent email, just go on + selenium.click("ui=commons::usertable_adduser_finish()"); + //selenium.waitForPageToLoad("30000"); + sleepThread(3000); + return true; + } else if(selenium.isElementPresent("ui=commons::anyLink(linkText=Next)")) { + //cancel wizard + selenium.click("ui=commons::usertable_adduser_cancelWizard()"); + selenium.waitForPageToLoad("30000"); + } + return false; + } + + public void removeAllWaiting() { + selectMembersTab(); + if (selenium.isElementPresent("ui=commons::usertable_waitingList_selectAll()")) { + selenium.click("ui=commons::usertable_waitingList_selectAll()"); + selenium.click("ui=commons::usertable_waitingList_remove()"); + selenium.waitForPageToLoad("30000"); + //per default is "Send e-mail" not checked + //selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + Send e-mail + ")") + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void removeAllParticipants() { + selectMembersTab(); + if (selenium.isElementPresent("ui=commons::usertable_participants_selectAll()")) { + selenium.click("ui=commons::usertable_participants_selectAll()"); + selenium.click("ui=commons::usertable_participants_remove()"); + selenium.waitForPageToLoad("30000"); + //per default is "Send e-mail" not checked + //selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + Send e-mail + ")") + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void removeParticipant(String userName, boolean confirmRemoval) { + selectMembersTab(); + selenium.check("ui=commons::usertable_userlist_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_participants_remove()"); + selenium.waitForPageToLoad("30000"); + //per default is "Send e-mail" not checked + //selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + Send e-mail + ")") + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + if(confirmRemoval) { + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void confirmRemove() { + selenium.click("ui=dialog::Yes()"); + } + + private void selectMembersTab() { + //go to the Members tab, if not already there + if(selenium.isElementPresent("ui=group::content_members_tabMembers()")) { + selenium.click("ui=group::content_members_tabMembers()"); + selenium.waitForPageToLoad("30000"); + } + } + + private void selectToolsTab() { + //go to the Tool tab, if not already there + if(selenium.isElementPresent("ui=group::content_tools_tabTools()")) { + selenium.click("ui=group::content_tools_tabTools()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * + * @return Returns a CourseRun instance. + */ + /*public CourseRun close() { + selenium.click("ui=groupManagement::toolbox_groupManagement_close()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + }*/ + + /** + * Change title and description, if in Administration page. + * @param groupName + * @param groupDescription + */ + public void setTitleAndDescription(String groupName, String groupDescription) { + //go to the Description tab, if not already there + if(selenium.isElementPresent("ui=group::content_description_tabDescription()")) { + selenium.click("ui=group::content_description_tabDescription()"); + selenium.waitForPageToLoad("30000"); + } + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Group name)", groupName); + //the description shows up in an iframe + selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", groupDescription); + selenium.selectFrame("relative=top"); + selenium.click("ui=commons::flexiForm_finishButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Toggle tool selection, if in Administration/Tools page. + * (e.g. if you want to change the selection ON/OFF for wiki, just pass true for this parameter) + * @param toggleInfo + * @param toggleContactForm + * @param toggleCalendar + * @param toggleFolder + * @param toggleForum + * @param toggleWiki + */ + public void setTools(boolean toggleInfo, boolean toggleContactForm, boolean toggleCalendar, boolean toggleFolder, boolean toggleForum, boolean toggleWiki, boolean toggleChat) { + selectToolsTab(); + if(toggleInfo) { + selenium.click("ui=group::content_tools_collaborationTools_information()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleContactForm) { + selenium.click("ui=group::content_tools_collaborationTools_contactForm()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleCalendar) { + selenium.click("ui=group::content_tools_collaborationTools_calendar()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleFolder) { + selenium.click("ui=group::content_tools_collaborationTools_folder()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleForum) { + selenium.click("ui=group::content_tools_collaborationTools_forum()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleWiki) { + selenium.click("ui=group::content_tools_collaborationTools_wiki()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + if(toggleChat && selenium.isElementPresent("ui=group::content_tools_collaborationTools_chat()")) { + selenium.click("ui=group::content_tools_collaborationTools_chat()"); + } + try { Thread.sleep(3000); } catch (Exception e) {} + //save button was removed + //selenium.click("ui=commons::flexiForm_saveButton()"); + //selenium.waitForPageToLoad("30000"); + } + + public boolean isChatSelected() { + selectToolsTab(); + return selenium.isChecked("ui=group::content_tools_collaborationTools_chat()"); + } + + public boolean isWikiSelected() { + selectToolsTab(); + return selenium.isChecked("ui=group::content_tools_collaborationTools_wiki()"); + } + + /** + * Sets info, only if the info text field is available. + * @param text + */ + public void setInfo(String text) { + // go to the Tool tab, if not already there + if(selenium.isElementPresent("ui=group::content_tools_tabTools()")) { + selenium.click("ui=group::content_tools_tabTools()"); + selenium.waitForPageToLoad("30000"); + } + //selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + if(selenium.isElementPresent("ui=group::content_tools_informationForMembers_formFieldInformationMembers()")) { + selenium.click("ui=group::content_tools_informationForMembers_formFieldInformationMembers()"); + selenium.type("ui=group::content_tools_informationForMembers_formFieldInformationMembers()", text); + //selenium.selectFrame("relative=top"); + selenium.click("ui=group::content_tools_informationForMembers_save()"); + } else { + throw new IllegalStateException("Select Info in Tools first!"); + } + } + + /** + * + * @param text + */ + public void selectCalendarWriteAccess(String text) { + // go to the Tool tab, if not already there + if(selenium.isElementPresent("ui=group::content_tools_tabTools()")) { + selenium.click("ui=group::content_tools_tabTools()"); + selenium.waitForPageToLoad("30000"); + } + if(selenium.isElementPresent("ui=group::content_tools_calendarAccess_save()") && !selenium.isChecked("ui=group::content_tools_calendarAccess_calendarAccess(label=" + text + ")")) { + selenium.click("ui=group::content_tools_calendarAccess_calendarAccess(label=" + text + ")"); + selenium.click("ui=group::content_tools_calendarAccess_save()"); + selenium.waitForPageToLoad("30000"); + } else if(!selenium.isElementPresent("ui=group::content_tools_calendarAccess_save()")) { + throw new IllegalStateException("Select Calendar in Tools first!"); + } + } + + /** + * Select the description tab, if not already there, and enable/disable waiting list and/or move up, save. + * @param maxParticipants + * @param hasWaitingList + * @param moveUp + */ + public void configureParticipantsAndWaitingList(int maxParticipants, Boolean hasWaitingList, Boolean moveUp) { + if(selenium.isElementPresent("ui=group::content_description_tabDescription()")) { + selenium.click("ui=group::content_description_tabDescription()"); + selenium.waitForPageToLoad("30000"); + } + selenium.type("ui=groupManagement::content_learningGroupsEditor_maxParticipants()", String.valueOf(maxParticipants)); + if (hasWaitingList!=null && hasWaitingList && !selenium.isChecked("ui=groupManagement::content_learningGroupsEditor_enableWaitinglist()")) { + //enableWaitinglist + selenium.check("ui=groupManagement::content_learningGroupsEditor_enableWaitinglist()"); + } else if (hasWaitingList!=null && !hasWaitingList && selenium.isChecked("ui=groupManagement::content_learningGroupsEditor_enableWaitinglist()")) { + selenium.uncheck("ui=groupManagement::content_learningGroupsEditor_enableWaitinglist()"); + } + if (moveUp!=null && moveUp && !selenium.isChecked("ui=groupManagement::content_learningGroupsEditor_moveUpAutomatically()")) { + //moveUpAutomatically + selenium.check("ui=groupManagement::content_learningGroupsEditor_moveUpAutomatically()"); + } else if (moveUp!=null && !moveUp && selenium.isChecked("ui=groupManagement::content_learningGroupsEditor_moveUpAutomatically()")) { + selenium.uncheck("ui=groupManagement::content_learningGroupsEditor_moveUpAutomatically()"); + } + + selenium.click("ui=commons::flexiForm_finishButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @return + */ + public Group start(String name) { + selenium.click("ui=group::menu_startCourse()"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + } + return new Group(selenium, name); + } + + /** + * + * @param groupName + */ + public void close(String groupName) { + if(selenium.isElementPresent("ui=tabs::closeGroup(nameOfGroup=" + groupName + ")")) { + selenium.click("ui=tabs::closeGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + } else { + System.out.println("Call GroupManager.close() to close this!"); + } + } + + public String getMaxNumParticipants() { + return selenium.getValue("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_maxParticipants()"); + } + + /** + * Change displayXXX if the corresponding input is not null. + * If one input param is null, do nothing for that one. + * @param dsiplayOwners + * @param displayParticipants + * @param displayWaitingList + */ + public void setMemberDisplayOptions(Boolean displayOwners, Boolean displayParticipants, Boolean displayWaitingList) { + selectMembersTab(); + //TODO: impl on/off displayOwners + sleepThread(3000); + + //TODO:LD: remove debug code! + if(!selenium.isTextPresent("Display members")) { + System.out.println("Display members - still unavailable"); + sleepThread(3000); + if(!selenium.isTextPresent("Display members")) { + System.out.println("Display members - still unavailable"); + } + } else if(selenium.isTextPresent("Members can see")){ + System.out.println("Members can see..."); + if(selenium.isTextPresent("Members can see participants")) { + System.out.println("Members can see participants"); + } + } + + //on/off displayParticipants + if(displayParticipants!=null && displayParticipants && !selenium.isChecked("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Members can see participants)")) { + selenium.click("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Members can see participants)"); + } else if(displayParticipants!=null && !displayParticipants && selenium.isChecked("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Members can see participants)")) { + selenium.uncheck("ui=commons::flexiForm_labeledCheckbox(formElementLabel=Members can see participants)"); + } + sleepThread(1000); + //TODO: impl on/off displayWaitingList + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupManagement.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupManagement.java new file mode 100644 index 0000000000000000000000000000000000000000..3701f6eaeb9aa64a6ef34673a9276d1f6e4f56c6 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/GroupManagement.java @@ -0,0 +1,245 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; + +import com.thoughtworks.selenium.Selenium; + +/** + * OLAT abstraction for the GroupManagement page. + * This is acquired via the CourseRun. + * + * @author Lavinia Dumitrescu + * + */ +public class GroupManagement extends OLATSeleniumWrapper { + + + /** + * @param selenium + */ + public GroupManagement(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isTextPresent("Group management")) { + throw new IllegalStateException("This is not the - Group management - page"); + } + } + + /** + * create new group with the given name, + * add one tutor to group, + * add one participant to the group, + * and close the group management. + * @param groupName + * @param userName + */ + public void createGroupAndAddMembers(String groupName, String tutorName, String participantName) { + //create new learning group + selenium.click("ui=groupManagement::toolbox_groupManagement_newLearningGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()", groupName); + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + selenium.waitForPageToLoad("30000"); + //add members + selenium.click("ui=group::content_members_tabMembers()"); + selenium.waitForPageToLoad("30000"); + //add tutor + if(tutorName!=null) { + selenium.click("ui=groupManagement::content_learningGroupsEditor_addMembers_addTutor()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", tutorName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser="+tutorName+")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } + //add participants + if(participantName!=null) { + selenium.click("ui=commons::usertable_participants_addUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", participantName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser="+participantName+")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=groupManagement::toolbox_groupManagement_close()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * If maxParticipants>0 type the value into the appropriate field. + * @param groupName + * @param description + * @param maxParticipants + * @param hasWaitingList + * @param moveUpAutomatically + * @return Returns the newly created GroupAdmin. + */ + public GroupAdmin createLearningGroup(String groupName, String description, int maxParticipants, boolean hasWaitingList, boolean moveUpAutomatically) { + + // create new learning group + selenium.click("ui=groupManagement::toolbox_groupManagement_newLearningGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_name()", groupName); + if(description!=null) { + //uses a Rich text element + selenium.type("ui=commons::tinyMce_styledTextArea()", description); + } + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + selenium.waitForPageToLoad("30000"); + + if(maxParticipants>0) { + selenium.type("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_maxParticipants()", String.valueOf(maxParticipants)); + } + if(hasWaitingList) { + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_enableWaitinglist()"); + } + if(moveUpAutomatically) { + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_moveUpAutomatically()"); + } + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + selenium.waitForPageToLoad("30000"); + + return new GroupAdmin(selenium); + } + + /** + * Select "All learning groups" and select the group with the given name. + * @param groupName + * @return Returns a GroupAdmin instance. + */ + public GroupAdmin editLearningGroup(String groupName) { + selenium.click("ui=groupManagement::menu_allLearningGroups()"); + selenium.waitForPageToLoad("30000"); + // if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=groupManagement::content_learningGroupTable_editLearningGroup(nameOfLearningGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + return new GroupAdmin(selenium); + } + + /** + * Selects the learning group with the given name. + * @param groupName + * @return + */ + public Group selectLearningGroup(String groupName) { + selenium.click("ui=groupManagement::menu_allLearningGroups()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groupManagement::content_learningGroupTable_selectGroup(nameOfGroup="+ groupName + ")"); + selenium.waitForPageToLoad("30000"); + return new Group(selenium, groupName); + } + + + /** + * + * @param areaName + * @param description + */ + public LearningArea createLearningArea(String areaName, String description) { + selenium.click("ui=groupManagement::toolbox_groupManagement_newLearningArea()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=groupManagement::toolbox_groupManagement_formNewLearningArea_name()", areaName); + if(description!=null) { + typeInRichText(description); + } + selenium.click("ui=commons::flexiForm_finishButton()"); + selenium.waitForPageToLoad("30000"); + + return new LearningArea(selenium); + } + + /** + * + * @param areaName + * @return + */ + public LearningArea editLearningArea(String areaName) { + selenium.click("ui=groupManagement::menu_allLearningAreas()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groupManagement::content_learningAreaTable_editLearningArea(nameOfLearningArea=learning area selenium 1)"); + selenium.waitForPageToLoad("30000"); + + return new LearningArea(selenium); + } + + /** + * + * @param userName + * @param groupName + */ + public void removeMemberFromGroup(String userName, String groupName) { + selenium.click("ui=groupManagement::menu_allMembers()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_userlist_clickUserName(nameOfUser="+userName+")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groupManagement::content_userDetails_removeFromGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @return Returns a CourseRun instance. + */ + public CourseRun close() { + selenium.click("ui=groupManagement::toolbox_groupManagement_close()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + + /** + * Deletes group only if such group found. + * @param groupName + */ + public void deleteGroup(String groupName) { + if(selenium.isElementPresent("ui=groupManagement::menu_allLearningGroups()")) { + selenium.click("ui=groupManagement::menu_allLearningGroups()"); + selenium.waitForPageToLoad("30000"); + } + if (selenium.isElementPresent("ui=groupManagement::content_learningGroupTable_deleteLearningGroup(nameOfLearningGroup=" + groupName + ")")) { + selenium.click("ui=groupManagement::content_learningGroupTable_deleteLearningGroup(nameOfLearningGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + System.out.println("Group deleted: " + groupName); + } else { + System.out.println("No such group found, could not delete group: " + groupName); + } + } +} + + diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/Groups.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/Groups.java new file mode 100644 index 0000000000000000000000000000000000000000..a3e3fa0d7f1200178c6b50321f1ebb19ecf0712c --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/Groups.java @@ -0,0 +1,108 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This represents the Groups tab. + * + * @author Lavinia Dumitrescu + * + */ +public class Groups extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public Groups(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isTextPresent("Groups")) { + throw new IllegalStateException("This is not the - Groups - page"); + } + } + + /** + * + * @param groupName + * @param groupDescription + * @return + */ + public GroupAdmin createProjectGroup(String groupName, String groupDescription) { + selenium.click("ui=groups::toolbox_create_projectGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Group name)", groupName); + //the description shows up in an iframe + selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", groupDescription); + selenium.selectFrame("relative=top"); + + selenium.click("ui=commons::flexiForm_finishButton()"); + selenium.waitForPageToLoad("30000"); + return new GroupAdmin(selenium); + } + + /** + * Deletes group with the given name. + * @param groupName + */ + public void deleteGroup(String groupName) { + selenium.click("ui=groups::content_deleteGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYes()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Leave group. + * @param groupName + */ + public void leaveGroup(String groupName) { + selenium.click("ui=groups::content_leaveGroup(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_leaveYes()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @param groupName + * @return Returns the selected group. + */ + public Group selectGroup(String groupName) { + selenium.click("ui=groups::content_clickGroupEntry(nameOfGroup=" + groupName + ")"); + selenium.waitForPageToLoad("30000"); + return new Group(selenium, groupName); + } + + public boolean hasGroup(String groupName) { + if(selenium.isElementPresent("ui=groups::content_clickGroupEntry(nameOfGroup=" + groupName + ")")) { + return true; + } + return false; + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/LearningArea.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/LearningArea.java new file mode 100644 index 0000000000000000000000000000000000000000..e5bbcd93f430b7b534b6dc260fb5bdc82406229e --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/LearningArea.java @@ -0,0 +1,59 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Lavinia Dumitrescu + * + */ +public class LearningArea extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public LearningArea(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isTextPresent("Edit learning area")) { + throw new IllegalStateException("This is not the - Edit learning area - page"); + } + } + + /** + * + * @param groupNames + */ + public void assignGroup(String[] groupNames) { + selenium.click("ui=groupManagement::content_learningAreaEditor_tabs_groupAssignment()"); + selenium.waitForPageToLoad("30000"); + for(String groupName:groupNames) { + selenium.click("ui=groupManagement::content_learningAreaEditor_groupAssignment_checkLearningGroup(nameOfGroup=" + groupName + ")"); + } + selenium.click("ui=groupManagement::content_learningAreaEditor_groupAssignment_save()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsAdmin.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsAdmin.java new file mode 100644 index 0000000000000000000000000000000000000000..264aafe372ae0df3847dc5bf03b4a6f2181fffe0 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsAdmin.java @@ -0,0 +1,64 @@ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * Page for Rightsgroup Administration + * @author Thomas Linowsky, BPS GmbH + * + */ + + +public class RightsAdmin extends OLATSeleniumWrapper{ + + /** + * Default constructor + * @param selenium + */ + public RightsAdmin(Selenium selenium){ + super(selenium); + } + + + /** + * Add members to Group (e.g. Rightsgroup) looping through Add user(s). + * @param members The usernames of the members to add + * @throws InterruptedException + */ + + public void addMembers(String[] members) throws InterruptedException{ + selectMembersTab(); + for(String userName:members) { + selenium.click("ui=commons::usertable_members_addUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + Thread.sleep(5000); + if(selenium.isElementPresent("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")")) { + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } else { + System.out.println("GroupAdmin.addMembers - since no user found, skip participant: " + userName); + } + } + } + + /** + * Go to Tab Members + */ + + private void selectMembersTab() { + //go to the Members tab, if not already there + if(selenium.isElementPresent("ui=group::content_members_tabMembers()")) { + selenium.click("ui=group::content_members_tabMembers()"); + selenium.waitForPageToLoad("30000"); + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsManagement.java b/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsManagement.java new file mode 100644 index 0000000000000000000000000000000000000000..186ae7d8ceb2ca03708418806cdbc4ceec89f6f2 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/group/RightsManagement.java @@ -0,0 +1,59 @@ +package org.olat.test.util.selenium.olatapi.group; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; + +/** + * Wrapper for Rights Management, triggered from Course Run + * + * @author Thomas Linowsky + */ + +import com.thoughtworks.selenium.Selenium; + +public class RightsManagement extends OLATSeleniumWrapper{ + + /** + * Constructor + * @param selenium + */ + public RightsManagement(Selenium selenium) { + super(selenium); + if(!selenium.isTextPresent("Rights management")) { + throw new IllegalStateException("This is not the - Rights management - page"); + } + } + + /** + * create a new rights group with given title and description + * @param title The title of the new rights group + * @param description The description of the new rights group + * @return The GroupAdmin object of the newly created rights group + */ + + public RightsAdmin createRightsGroup(String title, String description) { + selenium.click("ui=rightsManagement::createRightsGroup()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=group::content_description_groupDetails_groupName()", title); + if(description!=null) { + //uses a Rich text element + selenium.type("ui=commons::tinyMce_styledTextArea()", description); + } + selenium.click("ui=groupManagement::toolbox_groupManagement_formNewLearningGroup_save()"); + selenium.waitForPageToLoad("30000"); + + return new RightsAdmin(selenium); + } + + /** + * close the rights group and show Course run the group was inited by + * @return The courserun where we came from + */ + + public CourseRun closeRightsManagement() { + selenium.click("ui=rightsManagement::rightGroups_close()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/home/EvidencesOfAchievement.java b/src/test/java/org/olat/test/util/selenium/olatapi/home/EvidencesOfAchievement.java new file mode 100644 index 0000000000000000000000000000000000000000..f04b3a3d0297b02f127fa0c7218b61a9b62f2438 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/home/EvidencesOfAchievement.java @@ -0,0 +1,113 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.home; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is the EvidencesOfAchievement page. + * @author Lavinia Dumitrescu + * + */ +public class EvidencesOfAchievement extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public EvidencesOfAchievement(Selenium selenium) { + super(selenium); + // TODO check for label + } + + /** + * Get the Passed status for the courseName. + * @param courseName + * @return + */ + public String getCoursePassedStatus(String courseName) { + return selenium.getText("ui=home::content_evidencesOfAchievement_passedStatus(title=" + courseName + ")"); + } + + /** + * Starts course. + * @return + */ + public CourseRun startCourse(String title) { + selenium.click("ui=home::content_evidencesOfAchievement_startCourse(title=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + /** + * Selects the details page for the given course. + * @param courseName + * @throws Exception + */ + public void selectDetails(String courseName) throws Exception { + //if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=home::content_evidencesOfAchievement_selectDetails(title=" + courseName + ")"); + Thread.sleep(10000); + selenium.selectWindow(selenium.getAllWindowTitles()[2]); + assertTrue(selenium.isElementPresent("ui=home::content_evidencesOfAchievement_evidenceOfAchievement()")); + } + + /** + * Set the score for the courseElemTitle in the EvidenceOfAchievement details. + * @param courseElemTitle + * @return + */ + public String getCourseElementScore(String courseElemTitle) { + return selenium.getText("ui=course::assessment_scoreInTable(title=" + courseElemTitle + ")"); + } + + /** + * Get the passed status for the courseElemTitle in the EvidenceOfAchievement details. + * @param courseElemTitle + * @return + */ + public String getCourseElementPassedStatus(String courseElemTitle) { + return selenium.getText("ui=course::assessment_passedStatusInTable(title=" + courseElemTitle + ")"); + } + + public String getCourseElementAttempts(String courseElemTitle) { + return selenium.getText("ui=course::assessment_attemptsInTable(title=" + courseElemTitle + ")"); + } + + /** + * delete evidences of achievement for the courses containing courseName. + * @param courseName + */ + public void deleteAll(String courseName) { + while(selenium.isElementPresent("ui=home::content_evidencesOfAchievement_delete(title=" + courseName + ")")) { + System.out.println("Delete link found, delete evidence of achievement!"); + selenium.click("ui=home::content_evidencesOfAchievement_delete(title=" + courseName + ")"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + } + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/home/Home.java b/src/test/java/org/olat/test/util/selenium/olatapi/home/Home.java new file mode 100644 index 0000000000000000000000000000000000000000..602c86ed18883507ce95920949c8de3bf256f667 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/home/Home.java @@ -0,0 +1,110 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.home; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.folder.Folder; +import org.olat.test.util.selenium.olatapi.group.Group; +import org.olat.test.util.selenium.olatapi.portfolio.EPExtensions; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Lavinia Dumitrescu + * + */ +public class Home extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public Home(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isTextPresent("Welcome to OLAT")) { + throw new IllegalStateException("This is not the - Home - page"); + } + } + + /** + * Select the group in MyGroups portlet with the given name. + * @param title + * @return + */ + public Group selectMyGroup(String title) { + //increase number of entries for the "My groups" portlet + getHomeConfigurator().configMyGroupPortlet(99, HomeConfigurator.SORT_TYPE.ALPHABET, true); + + selenium.click("ui=home::content_portlets_myGroups(nameOfGroup=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new Group(selenium, title); + } + + /** + * Select the course in MyBookmarks portlets with the given title. + * @param title + * @return + */ + public CourseRun selectMyBookmarkedCourse(String title) { + //increase number of entries for the "My bookmarks" portlet + getHomeConfigurator().configMyBookmarkPortlet(99, HomeConfigurator.SORT_TYPE.ALPHABET, true); + + selenium.click("ui=home::content_portlets_myBookmarks(nameOfBookmark=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + + /** + * Selects the EvidencesOfAchievement. + * @return Returns the EvidencesOfAchievement page. + */ + public EvidencesOfAchievement getEvidencesOfAchievement() { + selenium.click("ui=home::menu_evidencesOfAchievement()"); + selenium.waitForPageToLoad("30000"); + return new EvidencesOfAchievement(selenium); + } + + public MySettings getUserSettings() { + selenium.click("ui=home::menu_settings()"); + selenium.waitForPageToLoad("30000"); + return new MySettings(selenium); + } + + public Folder getPersonalFolder() { + selenium.click("ui=home::menu_personalFolder()"); + selenium.waitForPageToLoad("30000"); + return new Folder(selenium); + } + + public HomeConfigurator getHomeConfigurator() { + selenium.click("ui=home::config_editConfig()"); + selenium.waitForPageToLoad("30000"); + return new HomeConfigurator(selenium); + } + + public EPExtensions getEPortfolio(){ + selenium.click("ui=home::menu_ePortfolio()"); + selenium.waitForPageToLoad("30000"); + return new EPExtensions(selenium); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/home/HomeConfigurator.java b/src/test/java/org/olat/test/util/selenium/olatapi/home/HomeConfigurator.java new file mode 100644 index 0000000000000000000000000000000000000000..9f91e85ba2e63e69075ee7c76f4e58c381821d2d --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/home/HomeConfigurator.java @@ -0,0 +1,65 @@ +package org.olat.test.util.selenium.olatapi.home; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +public class HomeConfigurator extends OLATSeleniumWrapper { + + public enum SORT_TYPE {TYPE, ALPHABET, DATE} + + + public HomeConfigurator(Selenium selenium) { + super(selenium); + // TODO: LD: Check that we're on the right place + } + + /** + * Configures only the numOfEntries. + * TODO: LD: add configuration after sortType and ascending. + * @param numOfEntries + * @param sortType + * @param ascending + * @return + */ + public Home configMyGroupPortlet(int numOfEntries, SORT_TYPE sortType, boolean ascending) { + //start auto config wizard + selenium.click("ui=home::config_autoConfigMyGroups()"); + selenium.waitForPageToLoad("30000"); + //do configure + configureCurrentSelectedPortlet(numOfEntries, sortType, ascending); + + return new Home(selenium); + } + + public Home configMyBookmarkPortlet(int numOfEntries, SORT_TYPE sortType, boolean ascending) { + selenium.click("ui=home::config_autoConfigMyBookmarks()"); + selenium.waitForPageToLoad("30000"); + //do configure + configureCurrentSelectedPortlet(numOfEntries, sortType, ascending); + + return new Home(selenium); + } + + /** + * Change num of entries if different of the current one. + * @param numOfEntries + * @param sortType + * @param ascending + */ + private void configureCurrentSelectedPortlet(int numOfEntries, SORT_TYPE sortType, boolean ascending) { + String currentNumOfEntries = selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=Number of entries in portlet)"); + if(!currentNumOfEntries.equals(String.valueOf(numOfEntries))) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Number of entries in portlet)", String.valueOf(numOfEntries)); + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + } else { + selenium.click("ui=commons::cancelButton()"); + selenium.waitForPageToLoad("30000"); + } + //close editor + selenium.click("ui=home::config_endConfig()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/home/MySettings.java b/src/test/java/org/olat/test/util/selenium/olatapi/home/MySettings.java new file mode 100644 index 0000000000000000000000000000000000000000..a9489bc44fb9212a0d674431ee9624d44201aebe --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/home/MySettings.java @@ -0,0 +1,174 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.home; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * The user settings in Home. + * @author Lavinia Dumitrescu + * + */ +public class MySettings extends OLATSeleniumWrapper { + + public MySettings(Selenium selenium) { + super(selenium); + + if(!selenium.isElementPresent("ui=home::content_settings_tabs_password()")) { + throw new IllegalStateException("This is not the - UserSettings - page"); + } + } + + /** + * + * @param newPassword + */ + public void setPassword(String newPassword) { + selectPasswordTab(); + selenium.type("ui=userManagement::content_userdetail_changePasswordTab_newPassword()", newPassword); + selenium.type("ui=userManagement::content_userdetail_changePasswordTab_confirmPassword()", newPassword); + + selenium.click("ui=commons::saveInput()"); + selenium.waitForPageToLoad("30000"); + } + + private void selectPasswordTab() { + if(selenium.isElementPresent("ui=home::content_settings_tabs_password()")) { + selenium.click("ui=home::content_settings_tabs_password()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Sets email and/or showOnVisitingCard status. + * @param email + * @param showOnVisitingCard + */ + public void setEmail(String email, Boolean showOnVisitingCard) { + selectProfileTab(); + setTextInput("E-mail", email, showOnVisitingCard); + selenium.click("ui=home::content_settings_profile_yesLink()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * + * @return + */ + public String getEmail() { + selectProfileTab(); + return getText("E-mail"); + } + + /** + * Gets the value for the labeled input element. + * @param label + * @return + */ + public String getText(String label) { + return selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=" + label + ")"); + } + + /*public String getDisabledText(String label) { + return selenium.getValue("ui=commons::flexiForm_disabledLabeledTextInput(formElementLabel=" + label + ")"); + }*/ + + private void setTextInput(String inputLabel, String text, Boolean showOnVisitingCard) { + if(text!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=" + inputLabel + ")", text); + } + if(showOnVisitingCard!=null) { + if(showOnVisitingCard) { + selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } else { + selenium.uncheck("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } + } + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * If showOnVisitingCard!=null, check/uncheck the show on visit card checkbox, depending on the boolean value. + * @param showOnVisitingCard + */ + public void showFirstNameOnVisitingCard(Boolean showOnVisitingCard) { + selectProfileTab(); + checkShowOnVisitingCard("First name", showOnVisitingCard); + } + + + private void checkShowOnVisitingCard(String inputLabel,Boolean showOnVisitingCard) { + if(showOnVisitingCard!=null) { + if(showOnVisitingCard) { + selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } else { + selenium.uncheck("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } + } + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Check if the input test is present as value for a disabled input field: e.g. firstname, lastname. + * @param text + * @return + */ + public boolean isDisabledTextPresent(String text) { + return selenium.isElementPresent("ui=commons::flexiForm_disabledTextInput(inputValue=" + text + ")"); + } + + /** + * Selects the System tab. + */ + private void selectSystemTab() { + if(selenium.isElementPresent("ui=home::content_settings_tabs_system()")) { + selenium.click("ui=home::content_settings_tabs_system()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Selects the profile tab, if not already there. + */ + private void selectProfileTab() { + if(selenium.isElementPresent("ui=home::content_settings_tabs_profile()")) { + selenium.click("ui=home::content_settings_tabs_profile()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Select System tab, if not already there, set language and save. + * @param languageLabel + */ + public void selectSystemLanguage(String languageLabel) { + selectSystemTab(); + selenium.select("language", "label=" + languageLabel); + selenium.click("ui=home::content_settings_system_general_save()"); + selenium.waitForPageToLoad("30000"); + } + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/i18n/LocalStringProvider.java b/src/test/java/org/olat/test/util/selenium/olatapi/i18n/LocalStringProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..e13220f68a39e2ca4f4aee35a209450c11e9d090 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/i18n/LocalStringProvider.java @@ -0,0 +1,14 @@ +package org.olat.test.util.selenium.olatapi.i18n; + +/** + * Provides some common local strings. + * @author Lavinia Dumitrescu + * + */ +public class LocalStringProvider { + + public static String COURSE_ALREADY_LOCKED_PREFIX = "This course is currently locked by"; + //pbl.confirm + public static String COURSE_PUBLISH_CONFIRM = "Please confirm the publication of the following course elements."; + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/BlogResource.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/BlogResource.java new file mode 100644 index 0000000000000000000000000000000000000000..19d0375f9a0c269298efad8d4884859b5cc39169 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/BlogResource.java @@ -0,0 +1,150 @@ +package org.olat.test.util.selenium.olatapi.lr; + +import com.thoughtworks.selenium.Selenium; + +public class BlogResource extends ResourceEditor { + + public BlogResource(Selenium selenium, String title) { + super(selenium, title); + // TODO Auto-generated constructor stub + } + + /** + * + * @param title + * @param description + * @param imageName + */ + public void editBlog(String title, String description, String imageName) { + selenium.click("ui=blog::edit()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + selenium.type("ui=commons::tinyMce_styledTextArea()", description); + + if(imageName!=null) { + //TODO: LD: add image + } + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Create blog entry. + * @param title + * @param description + * @param content + * @param publish TODO + */ + public void createEntry(String title, String description, String content, boolean publish) { + if(selenium.isElementPresent("ui=blog::create()")) { + selenium.click("ui=blog::create()"); + selenium.waitForPageToLoad("30000"); + } else if(selenium.isElementPresent("ui=blog::createNewEntry()")) { + selenium.click("ui=blog::createNewEntry()"); + selenium.waitForPageToLoad("30000"); + } + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + this.sleepThread(3000); + + editBlogEntry(description, content, publish); + } + + /** + * This edits an existing entry, therefore if description or content are null, they don't get changed. + * The title cannot be null. + * + * @param title + * @param description + * @param content + * @param publish + */ + public void editEntry(String title, String description, String content, boolean publish) { + selenium.click("ui=blog::editEntry(entryTitle=" + title + ")"); + //selenium.waitForPageToLoad("30000"); + this.sleepThread(3000); + + editBlogEntry(description, content, publish); + } + + private void editBlogEntry(String description, String content, boolean publish) { + if(description!=null) { + selenium.selectFrame("ui=blog::blogEntryDescriptionFrame()"); + selenium.type("ui=commons::tinyMce_styledTextArea()", description); + selenium.selectFrame("relative=top"); + } + + this.sleepThread(3000); + if(content!=null && selenium.isElementPresent("ui=blog::blogEntryContentFrame()")) { + selenium.selectFrame("ui=blog::blogEntryContentFrame()"); + selenium.type("ui=commons::tinyMce_styledTextArea()", content); + selenium.selectFrame("relative=top"); + } + + if(publish) { + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Publish)"); + selenium.waitForPageToLoad("30000"); + } else { + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Save draft)"); + selenium.waitForPageToLoad("30000"); + } + } + + public boolean hasDraftEntry(String entryTitle) { + return selenium.isElementPresent("ui=blog::draft(entryTitle=" + entryTitle + ")"); + } + + /** + * Add one comment and go back to the blog view. + * + * @param entryTitle + * @param comment + */ + public void commentEntry(String entryTitle, String comment) { + selenium.click("ui=blog::addComment(entryTitle=" + entryTitle + ")"); + selenium.waitForPageToLoad("30000"); + this.sleepThread(5000); + + //typeInRichText(comment); + selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", comment); + selenium.selectFrame("relative=top"); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::backLink()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * TODO: fix this implementation. It does not use the entryTitle. + * @param entryTitle + * @param num + * @return + */ + public boolean hasComments(String entryTitle, int num) { + return selenium.isTextPresent("Comments (" + num + ")"); + } + + /** + * Include external blog. + * Suppose that a valid feedURL is provided. + * @param title + * @param description + * @param feedURL + */ + public void includeExternalBlog(String title, String description, String feedURL) { + selenium.click("ui=blog::includeExternal()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Description)", description); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Feed URL)", feedURL); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: if no valid URL is provided, cancel or enter a new URL + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/CPResourceEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/CPResourceEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..bebd9deddcaa5218a72be2ce90d1b7cb1f46be54 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/CPResourceEditor.java @@ -0,0 +1,227 @@ +package org.olat.test.util.selenium.olatapi.lr; + + +import com.thoughtworks.selenium.Selenium; + +public class CPResourceEditor extends ResourceEditor { + + public CPResourceEditor(Selenium selenium, String title) { + super(selenium, title); + //Check that we're on the right place + if(!selenium.isElementPresent("ui=cpEditor::addPage()")) { + throw new IllegalStateException("This is not the - CPResourceEditor - page"); + } + } + + /** + * Changes title of the page assuming that the page is visible to be selected before. + * @param currentTitle + * @param newTitle + */ + public void changeTitle(String currentTitle, String newTitle) { + selectPage(currentTitle); + changeCurrentTitle(newTitle); + } + + /** + * Uses only saveAndClose. + * + * @param newTitle + */ + private void changeCurrentTitle(String newTitle) { + selenium.click("ui=cpEditor::editPageProperties()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=cpEditor::metadataTitleInput()", newTitle); + selenium.click("ui=cpEditor::saveAndClose()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Selects the page with this title, if visible. + * As with selecting the node the subtree opens. + * @param title + * @return Returns true if page gets selected, else false. + */ + private boolean selectPage(String title) { + //if link exists but it is not selected + if(selenium.isElementPresent("ui=cpEditor::menuTreeLink(link=" + title + ")") + && !selenium.isElementPresent("ui=cpEditor::selectedTreeNodeExpanded(link=" + title + ")") + && !selenium.isElementPresent("ui=cpEditor::selectedTreeNodeLeaf(link=" + title + ")")) { + selenium.click("ui=cpEditor::menuTreeLink(link=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return true; + } + //no such page found + return false; + } + + /** + * Add page, after selecting the parent page, assuming that this is visible. + * Renames page. + * + * @param parentTitle + * @param title + * @param content + */ + public void addPageAndRename(String parentTitle, String title, String content) { + selectPage(parentTitle); + //add page + selenium.click("ui=cpEditor::addPage()"); + selenium.waitForPageToLoad("30000"); + //changeTitle + changeCurrentTitle(title); + //add some content + selenium.type("ui=commons::tinyMce_styledTextArea()", content); + selenium.click("ui=commons::saveLink()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Sets content to the page named title. + * + * @param title + * @param content + */ + public void editPage(String title, String content) { + selectPage(title); + //replace content + selenium.type("ui=commons::tinyMce_styledTextArea()", content); + selenium.click("ui=commons::saveLink()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Copies and renames the copy page. + * + * @param sourceTitle + * @param targetTitle + */ + public void copyPageAndRename(String sourceTitle, String targetTitle) { + copyPage(sourceTitle); + //changeTitle + changeCurrentTitle(targetTitle); + } + + /** + * Select source page and press copy, creates a copy with the default title. + * + * @param sourceTitle + * @param targetTitle + */ + public void copyPage(String sourceTitle) { + selectPage(sourceTitle); + //copy page + selenium.click("ui=cpEditor::copyPage()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Select parent and import file. + * @param parentTitle + * @param archiveFileName + */ + public void importPage(String parentTitle, String fileName) { + selectPage(parentTitle); + //import page + selenium.click("ui=cpEditor::importPage()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=upload::fileChooser()", fileName); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Import)"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Select page and delete. + * @param currentTitle + * @param deleteMenuElementOnly + */ + public void deletePage(String currentTitle, boolean deleteMenuElementOnly) { + selectPage(currentTitle); + //delete page + selenium.click("ui=cpEditor::deletePage()"); + selenium.waitForPageToLoad("30000"); + //choose delete type + if(deleteMenuElementOnly) { + selenium.click("ui=commons::anyLink(linkText=Delete menu element only)"); + } else { + selenium.click("ui=commons::anyLink(linkText=Delete menu element and files)"); + } + selenium.waitForPageToLoad("30000"); + } + + /** + * Drags and drops from the sourceTitle to the targetTitle. + * + * @param sourceTitle + * @param targetTitle + */ + public void movePage(String sourceTitle, String targetTitle) { + //TODO:LD: fix this!!! + + //selenium.dragAndDropToObject("ui=cpEditor::dragAndDropSrcObject(link=" + sourceTitle + ")", "ui=cpEditor::dragAndDropSrcObject(link=" + targetTitle + ")"); + selenium.mouseDownAt("ui=cpEditor::dragAndDropSrcObject(link=" + sourceTitle + ")","10,10"); + selenium.mouseMoveAt("ui=cpEditor::dragAndDropSrcObject(link=" + targetTitle + ")","10,10"); + selenium.mouseOver("ui=cpEditor::dragAndDropSrcObject(link=" + targetTitle + ")"); + selenium.mouseUpAt("ui=cpEditor::dragAndDropSrcObject(link=" + targetTitle + ")","10,10"); + + //selenium.waitForPageToLoad("30000"); + } + + /** + * TODO LD: check this out!!! Open, close preview, is this OK? + * @param title + * @return + */ + public void preview(String title) { + selectPage(title); + //press preview + selenium.click("ui=cpEditor::preview()"); + selenium.waitForPageToLoad("30000"); + //close preview + selenium.click("ui=commons::anyLink(linkText=Close preview)"); + selenium.waitForPageToLoad("30000"); + } + + + /** + * Inserts image, steps: + * click symbol "insert/edit image" <br/> + * add Image description <br/> + * click "Browse" <br/> + * click "Upload file" <br/> + * click Select file and select filename <br/> + * click "Upload" <br/> + * click "Insert" <br/> + * click "save" <br/> + * + * @param filename + */ + public void insertImage(String filename, String description) { + selenium.click("ui=commons::tinyMce_insertEditImage()"); + this.sleepThread(3000); + selenium.selectFrame("//iframe[contains(@src,'/image.htm')]"); + + //add description + selenium.type("ui=cpEditor::imageDescription()", description); + + selenium.click("ui=commons::tinyMce_browse()"); + + //upload file + this.sleepThread(10000); + selenium.selectWindow(selenium.getAllWindowTitles()[2]); + selenium.click("ui=cpEditor::uploadFile()"); + this.sleepThread(10000); + //select file + selenium.type("ui=upload::fileChooser()",filename); + selenium.click("ui=upload::submit()"); + selenium.selectWindow(selenium.getAllWindowTitles()[1]); + + //insert image + selenium.click("ui=cpEditor::insertImage()"); + + //save + selenium.click("ui=commons::saveLink()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/Catalog.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/Catalog.java new file mode 100644 index 0000000000000000000000000000000000000000..adb70f929a6632db84df32e09ff6d8be0790028c --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/Catalog.java @@ -0,0 +1,36 @@ +package org.olat.test.util.selenium.olatapi.lr; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + + +/** + * Wrapper for the catalog view + * @author Thomas Linowsky, BPS GmbH + * + */ + +public class Catalog extends OLATSeleniumWrapper{ + + /** + * Default constructor + * @param selenium + */ + public Catalog(Selenium selenium){ + super(selenium); + } + + /** + * Check whether a catalog entry with given name exists + * @param name The name of the resource to check for + * @return true if the resource exists in the catalog + */ + + public boolean isEntryAvailable(String name){ + return selenium.isElementPresent("ui=learningResources::content_clickCatalogEntry(nameOfLearningResource="+name+")"); + } + + + +} \ No newline at end of file diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/CourseWizard.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/CourseWizard.java new file mode 100644 index 0000000000000000000000000000000000000000..029e39ef8e80e4e9453f327b624658325ad98fbf --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/CourseWizard.java @@ -0,0 +1,126 @@ +package org.olat.test.util.selenium.olatapi.lr; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +/** + * Wrapper for Course wizard + * + * This Class provides a wrapper for the course wizard which helps users to create a simple course + * + * @author Thomas Linowsky, BPS GmbH + * + * + */ + +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; + +import com.thoughtworks.selenium.Selenium; + + +public class CourseWizard extends OLATSeleniumWrapper{ + + /** + * Default constructor + * @param selenium + */ + + public CourseWizard(Selenium selenium) { + super(selenium); + } + + /** + * Select course elements that should be created. Possible elements are + * + * @param singlePage A Single Page with some text + * @param enrollment An Enrollment + * @param downloadFolder A download Folder + * @param forum a forum + * @param contactForm a contact form + */ + + public void selectCourseElements(boolean singlePage, boolean enrollment, boolean downloadFolder, boolean forum, boolean contactForm){ + if(singlePage){ + selenium.click("ui=learningResources::courseWizard_createSinglePage()"); + } + if(enrollment){ + selenium.click("ui=learningResources::courseWizard_createEnrollment()"); + } + if(downloadFolder){ + selenium.click("ui=learningResources::courseWizard_createDownloadFolder()"); + } + if(forum){ + selenium.click("ui=learningResources::courseWizard_createForum()"); + } + if(contactForm){ + selenium.click("ui=learningResources::courseWizard_createContactForm()"); + } + } + + /** + * Edit the enrollment properties. Select all CBBs that should be affected by this changes + * + * @param accessLimit whether the selected CBBs should be hidden if not enrolled + * @param singlePage whether the single page should be hidden + * @param downloadFolder whether the download folder should be hidden + * @param forum whether the forum should be hidden + * @param contactForm whether the contact form should be hidden + */ + + public void editEnrollment(boolean accessLimit, boolean singlePage, boolean downloadFolder, boolean forum, boolean contactForm){ + selenium.click("ui=learningResources::courseWizard_editEnrollmentLink()"); + selenium.waitForPageToLoad("30000"); + if(accessLimit){ + selenium.click("ui=learningResources::courseWizard_editEnrollment_accessLimit()"); + if(singlePage){ + selenium.click("ui=learningResources::courseWizard_editEnrollment_selectSP()"); + } + if(downloadFolder){ + selenium.click("ui=learningResources::courseWizard_editEnrollment_selectBC()"); + } + if(forum){ + selenium.click("ui=learningResources::courseWizard_editEnrollment_selectFO()"); + } + if(contactForm){ + selenium.click("ui=learningResources::courseWizard_editEnrollment_selectCO()"); + } + } + selenium.click("ui=commons::flexiForm_saveButton()"); + } + + /** + * Create the course and run it, providing access with @param publishLabel + * @param publishLabel The label to use for access + * @return A CourseRun from the created course + */ + + public CourseRun createCourseAndRun(String publishLabel){ + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + // skip catalog entry + selenium.click("ui=learningResources::courseWizard_catalogRoot()"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.select("ui=courseEditor::publishDialog_courseAccessDropDown()", "label="+publishLabel); + //TODO: LD: add here check if next selectable, else finish + if(selenium.isElementPresent("ui=courseEditor::publishDialog_next()")) { + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=courseEditor::publishDialog_finish()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + + } + + /** + * Create the course and run it, providing access with default ("All registered OLAT users") publish Label + * @return The resulting CourseRun object + */ + + public CourseRun createCourseAndRun(){ + return createCourseAndRun("All registered OLAT users"); + } + + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/LRDetailedView.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/LRDetailedView.java new file mode 100644 index 0000000000000000000000000000000000000000..d30f9e9a6ba6362fb8f6bf1d8ea082f0a8228b8b --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/LRDetailedView.java @@ -0,0 +1,386 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.lr; + +import org.olat.test.util.selenium.olatapi.CannotExecuteException; +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.DisposedCourseRun; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; + +import com.thoughtworks.selenium.Selenium; + +/** + * OLAT abstraction for the Detailed view of learning resource. + * + * @author Lavinia Dumitrescu + * + */ +public class LRDetailedView extends OLATSeleniumWrapper { + + public static final String ACCESS_ALL_REGISTERED = "All registered OLAT users"; + public static final String ACCESS_REGISTERED_AND_GUESTS = "Registered OLAT users and guests"; + public static final String ACCESS_OWNERS_AND_AUTHORS = "Owners and other OLAT authors"; + public static final String ACCESS_ONLY_OWNERS = "Only owners of this learning resource"; + + /** + * @param selenium + */ + public LRDetailedView(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=learningResources::content_showContent()")) { + throw new IllegalStateException("This is not the - Detailed view - page"); + } + } + + /** + * Deletes this learning resource, if possible. + * If not possible to delete this LR, go back to the Learning resources, + * and throw new CannotExecuteException. + * + * @return + * @throws CannotExecuteException + */ + public LearningResources deleteLR() { + selenium.click("ui=learningResources::toolbox_learningResource_delete()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=groups::content_deleteYesLs()"); + //delete course takes very long since 12.01.2010 (the course logs are also deleted) + selenium.waitForPageToLoad("150000"); + //This learning resource cannot be deleted + if(selenium.isTextPresent("This learning resource cannot be deleted.")) { + //click OK + selenium.click("ui=dialog::OK()"); + //back to resource list + selenium.click("ui=courseEditor::publishDialog_back()"); + selenium.waitForPageToLoad("30000"); + throw new CannotExecuteException("Cannot delete resource!"); + } + return new LearningResources(selenium); + } + + /** + * Modify properties. + * Modify access if necessary. + * @param accessLabel + */ + public void modifyProperties(String accessLabel) { + //open the LR Settings dialog + selenium.click("ui=learningResources::toolbox_learningResource_modifyProperties()"); + selenium.waitForPageToLoad("30000"); + //change access + boolean accessChanged = false; + if(ACCESS_ALL_REGISTERED.equals(accessLabel) && !selenium.isChecked("ui=learningResourcesModifieProperties::accessAllRegistered()")) { + selenium.click("ui=learningResourcesModifieProperties::accessAllRegistered()"); + accessChanged = true; + } else if(ACCESS_REGISTERED_AND_GUESTS.equals(accessLabel) && !selenium.isChecked("ui=learningResourcesModifieProperties::accessRegisteredAndGuests()")) { + selenium.click("ui=learningResourcesModifieProperties::accessRegisteredAndGuests()"); + accessChanged = true; + } else if(ACCESS_OWNERS_AND_AUTHORS.equals(accessLabel) && !selenium.isChecked("ui=learningResourcesModifieProperties::accessOwnersAndAuthors()")) { + selenium.click("ui=learningResourcesModifieProperties::accessOwnersAndAuthors()"); + accessChanged = true; + } else if (ACCESS_ONLY_OWNERS.equals(accessLabel) && !selenium.isChecked("ui=learningResourcesModifieProperties::accessOnlyOwners()")) { + selenium.click("ui=learningResourcesModifieProperties::accessOnlyOwners()"); + accessChanged = true; + } + if(accessChanged) { + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + //confirm modification of settings (new step in modify properties) + if(selenium.isElementPresent("ui=learningResources::dialog_yes()")) { + selenium.click("ui=learningResources::dialog_yes()"); + selenium.waitForPageToLoad("30000"); + } + } else { + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + } + + } + + /** + * Show course content. + * @return + */ + public CourseRun showCourseContent() { + selenium.click("ui=learningResources::content_showContent()"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + + /** + * Show wiki content. + * @return + */ + public WikiRun showWikiContent() { + selenium.click("ui=learningResources::content_showContent()"); + //selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + //e.printStackTrace(); + } + return new WikiRun(selenium); + } + + /** + * Click Edit content for a course detailed view. + * @return a new CourseEditor instance. + */ + public CourseEditor editCourseContent() { + //TODO: LD: add a string independent for the resource type + if(selenium.isTextPresent("Type") && selenium.isTextPresent("Course")) { + selenium.click("ui=learningResources::toolbox_learningResource_editContent()"); + selenium.waitForPageToLoad("30000"); + + return new CourseEditor(selenium); + } + throw new IllegalStateException("This is not a course detailed view"); + } + + /** + * Try to edit the course who was already been open, and got disposed. + * The user sees the "Close and restart course" button. + * @return + */ + public DisposedCourseRun selectDisposedCourse() { + selenium.click("ui=learningResources::toolbox_learningResource_editContent()"); + selenium.waitForPageToLoad("30000"); + return new DisposedCourseRun(selenium); + + } + + /** + * Start editing test. + * @return a new TestEditor instance. + */ + public TestEditor editTestContent() { + //TODO: LD: add a string independent for the resource type + if(selenium.isTextPresent("Type") && selenium.isTextPresent("Test")) { + selenium.click("ui=learningResources::toolbox_learningResource_editContent()"); + selenium.waitForPageToLoad("30000"); + + return new TestEditor(selenium); + } + throw new IllegalStateException("This is not a test detailed view"); + } + + /** + * The user tries to open the courseEditor but it is locked. + * The caller of this method expects to find the course locked, so it should not open the CourseEditor. + * + * @return Returns true if the "alreadyLocked" message shows up, false otherwise. + */ + public boolean checkCourseLocked(String lockOwnerUsername) throws Exception { + // TODO: LD: add a string independent for the resource type + if(selenium.isTextPresent("Type") && selenium.isTextPresent("Course")) { + selenium.click("ui=learningResources::toolbox_learningResource_editContent()"); + + // and wait until 'This course is currently edited by lockOwnerUsername and therefore locked.' appears + for (int second = 0;; second++) { + if (second >= 20) return false; + try { //WARNING: HERE POTENTIAL FAILURE EACH TIME THE TRANSLATION CHANGES! + if (selenium.isTextPresent("This course is being edited by "+lockOwnerUsername+" and therefore locked.")) + return true; + } catch (Exception e) {} + + Thread.sleep(1000); + } + } + throw new IllegalStateException("This is not a course detailed view"); + } + + + public void setBookmark() { + selenium.click("ui=course::toolbox_generalTools_setBookmark()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::saveInput()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Assign new owner. + * @param userName + */ + public void assignOwner(String userName) { + selenium.click("ui=learningResources::toolbox_learningResource_assignOwners()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_assignOwners_addOwner()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser="+ userName +")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Assign new owners. + * It selects all users received by filtering with userName. + * + * @param userName + */ + public void assignOwners(String userName) { + selenium.click("ui=learningResources::toolbox_learningResource_assignOwners()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::toolbox_learningResource_assignOwners_addOwner()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", userName); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_userlist_selectAll()"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Remove userName as owner of this learning resource. + * @param userName + * @return Returns Boolean.TRUE if the owner was successfully removed, + * Boolean.FALSE if the owner is the last one in group, + * and null if none of the above is true. + */ + public Boolean removeOwner(String userName) { + Boolean successfullyRemoved = null; + + selenium.click("ui=learningResources::toolbox_learningResource_assignOwners()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_checkUsernameToRemove(nameOfUser=" + userName + ")"); + selenium.click("ui=commons::usertable_removeOwner()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isTextPresent("Do you really want to remove")) { + selenium.click("ui=dialog::Yes()"); + selenium.waitForPageToLoad("30000"); + successfullyRemoved = true; + } else { + for (int second = 0; second < 20; second++) { + try { + if (selenium.isTextPresent("At least one user is required in a group.")) { + successfullyRemoved = false; + break; + } + } + catch (Exception e) {} + } + } + selenium.click("ui=overlay::overlayClose()"); + selenium.waitForPageToLoad("30000"); + + return successfullyRemoved; + } + + /** + * Get the String of the Access value + * + * Returns the value of course access, e.g. only owners + * + * @return value of course access + */ + public String getAccessString(){ + return selenium.getText("ui=learningResources::content_selectedAccessLabel()"); + } + + /** + * Make a copy of the current learning resource, withj the given title and description. + * + * @param newTitle + * @param newDescription could be null, keeps the old description + */ + public LearningResources copyLR(String newTitle, String newDescription) { + if(selenium.isElementPresent("ui=learningResources::toolbox_learningResource_copy()")) { + selenium.click("ui=learningResources::toolbox_learningResource_copy()"); + selenium.waitForPageToLoad("30000"); + try { //TODO: LD: is this really needed? + Thread.sleep(5000); + } catch (InterruptedException e) { + } + selenium.type("ui=learningResources::dialog_title()", newTitle); + if(newDescription!=null) { + selenium.type("ui=learningResources::dialog_description()", newDescription); + } + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + //selenium.waitForPageToLoad("30000"); + } else { + throw new IllegalStateException("Cannot copy learning resource!"); + } + return new LearningResources(selenium); + } + + public void exportLR() { + selenium.click("ui=learningResources::toolbox_learningResource_exportContent()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Close the course with dialog + * + * @param cleanCatalog clean catalog entries? + * @param cleanGroup clean group entries? + * + * @author Thomas Linowsky + */ + + public void closeCourse(boolean cleanCatalog, boolean cleanGroup){ + selenium.click("ui=learningResources::toolbox_learningResource_closeCourse()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + if(cleanCatalog){ + selenium.click("ui=learningResources::closeCourseWizard_cleanCatalog()"); + } + if(cleanGroup){ + selenium.click("ui=learningResources::closeCourseWizard_cleanGroup()"); + } + selenium.click("ui=learningResources::dialog_buttonNext()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::dialog_buttonNext()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Add the course to Catalog root + * + * @author Thomas Linowsky + */ + + public void addToCatalog(){ + selenium.click("ui=learningResources::toolbox_learningResource_addToCatalog()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::dialog_catalogRoot()"); + selenium.click("ui=dialog::select()"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/LearningResources.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/LearningResources.java new file mode 100644 index 0000000000000000000000000000000000000000..71de1b77175d09758661c5c345151f06d467dae1 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/LearningResources.java @@ -0,0 +1,609 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.lr; + +import java.io.File; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.course.editor.CourseEditor; +import org.olat.test.util.selenium.olatapi.course.run.CourseRun; +import org.olat.test.util.selenium.olatapi.course.run.WikiRun; +import org.olat.test.util.selenium.olatapi.qti.QuestionnaireEditor; +import org.olat.test.util.selenium.olatapi.qti.TestEditor; +import org.olat.test.util.setup.context.Context; + +import com.thoughtworks.selenium.Selenium; + +/** + * OLAT abstraction for the Learning Resources tab. + * Provides methods for the most common workflows. + * + * @author Lavinia Dumitrescu + * + */ +public class LearningResources extends OLATSeleniumWrapper { + + + public enum LR_Types {COURSE, TEST, WIKI, GLOSSARY, QUESTIONNAIRE, RESOURCE_FOLDER, BLOG, PODCAST, CP} + + /** + * @param selenium + */ + public LearningResources(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=learningResources::menu_searchForm()")) { + throw new IllegalStateException("This is not the - Learning resources - page"); + } + } + + /** + * Create resource with the given type, but do not start editing. + * @param title + * @param description + * @param type + * @return Returns a LRDetailedView object. + */ + public LRDetailedView createResource(String title, String description, LR_Types type) { + createResourceWithoutStartEdit(title, description, type); + if(LR_Types.COURSE.equals(type)) { + //new course wizard + //choose: create course with wizard, start course editor, or show detail view + selenium.click("ui=learningResources::courseImport_wizardShowDetailsView()"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + } else if(!LR_Types.WIKI.equals(type)) { + //if the resource type is not wiki, the start dialog should show up + selenium.click("ui=learningResources::dialog_startNo()"); + selenium.waitForPageToLoad("60000"); + try { //TODO: LD: is this really needed? + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + return new LRDetailedView(selenium); + } + + /** + * Clicks on the create XXX_resource button, fills the title and description, and clicks next. + * @param title + * @param description + * @param type + */ + private void createResourceWithoutStartEdit(String title, String description, LR_Types type) { + if(LR_Types.COURSE.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_course()"); + } else if(LR_Types.GLOSSARY.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_glossary()"); + } else if(LR_Types.WIKI.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_wiki()"); + } else if(LR_Types.QUESTIONNAIRE.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_questionnaire()"); + } else if(LR_Types.RESOURCE_FOLDER.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_resourceFolder()"); + } else if(LR_Types.TEST.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_test()"); + } else if(LR_Types.BLOG.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_blog()"); + } else if(LR_Types.PODCAST.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_podcast()"); + } else if (LR_Types.CP.equals(type)) { + selenium.click("ui=learningResources::toolbox_create_createCP()"); + } + + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::dialog_title()"); + selenium.type("ui=learningResources::dialog_title()", title); + + //SR: + selenium.setSpeed("1000"); + + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", description); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("60000"); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + } + + /** + * + * @param title + * @param description + */ + public void createGlossaryAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.GLOSSARY); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: return a Glossary object if needed + } + + /** + * + * @param title + * @param description + * @return + */ + public CourseEditor createCourseAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.COURSE); + + selenium.click("ui=learningResources::courseImport_wizardStartCourseEditor()"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + + return new CourseEditor(selenium); + } + + /** + * Create a new Course wizard by creating new course + * @param title The title of the course + * @param description The description of the course + * @return A CourseWizard object that represents the wizard component + * + * @author Thomas Linowsky + */ + + public CourseWizard createCourseWizard(String title, String description){ + createResourceWithoutStartEdit(title, description, LR_Types.COURSE); + + selenium.click("ui=learningResources::courseWizard_selectWizardRadio()"); + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Next)"); + selenium.waitForPageToLoad("30000"); + return new CourseWizard(selenium); + } + + /** + * + * @param title + * @param description + * @return + */ + public TestEditor createTestAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.TEST); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + + return new TestEditor(selenium); + } + + /** + * + * @param title + * @param description + * @return + */ + public QuestionnaireEditor createQuestionnaireAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.QUESTIONNAIRE); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + + return new QuestionnaireEditor(selenium); + } + + /** + * + * @param title + * @param description + */ + public ResourceEditor createResourceFolderAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.RESOURCE_FOLDER); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: return a ResourceFolderEditor if neccessary + return new ResourceEditor(selenium, title); + } + + /** + * Creates blog resource and opens it in a new tab. + * @param title + * @param description + * @return + */ + public BlogResource createBlogAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.BLOG); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + return new BlogResource(selenium, title); + } + + /** + * Creates podcast resource and opens it in a new tab. + * @param title + * @param description + * @return + */ + public PodcastResource createPodcastAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.PODCAST); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + return new PodcastResource(selenium, title); + } + + /** + * Select "Search form" and find the resource with the given title if provided, + * and with the given author if any provided. + * The title and the author could be null if not used for filtering. + * TODO : LD: filter after the resource type + * <br/> + * Could return null, if no resource found. + * + * @param selenium + * @param title + * @param author could be null + * @return Returns a LRDetailedView instance if a resource was found, null otherwise + */ + public LRDetailedView searchResource(String title, String author) { + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + + if(title!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", title); + } + if(author!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Author)", author); + } + //uncheck course type, if already checked + /*if(selenium.isChecked("ui=learningResources::content_searchForm_courseType()")) { + selenium.uncheck("ui=learningResources::content_searchForm_courseType()"); + }*/ + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + // if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + + if(selenium.isTextPresent(title) && selenium.isElementPresent("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + title + ")")) { + selenium.click("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new LRDetailedView(selenium); + } + //no resource found + return null; + } + + /** + * Search resource and show the course content with the input title. + * @param title + * @return Returns a CourseRun instance if a course with the given name is found, else returns null. + */ + public CourseRun searchAndShowCourseContent (String title) { + selenium.click("ui=learningResources::menu_searchForm()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title of learning resource)", title); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + //if too many entries found - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + title + ")"); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + selenium.waitForPageToLoad("60000"); + + return new CourseRun(selenium); + } + + /** + * Select "My Entries", if too many [Show all] link present, click [Show all], + * and select the entry with the input name. + * + * @param selenium + * @param entryName + * @return + */ + public LRDetailedView searchMyResource(String title) { + selenium.click("ui=learningResources::menu_myEntries()"); + selenium.waitForPageToLoad("30000"); + //if too many entries in myEntries - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=learningResources::content_showDetailedView(nameOfLearningResource=" + title + ")"); + selenium.waitForPageToLoad("30000"); + + return new LRDetailedView(selenium); + } + + /** + * Search and open a course from "My Entries". + * @param title + * @return + */ + public CourseRun searchAndShowMyCourseContent(String title) { + selenium.click("ui=learningResources::menu_myEntries()"); + selenium.waitForPageToLoad("30000"); + //if too many entries in myEntries - show all + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + title + ")"); + selenium.waitForPageToLoad("30000"); + + return new CourseRun(selenium); + } + + /** + * Selects the "Courses" link, and next clicks on "Show content" of the course with the + * given title. It assumes that the course is visible on the first page of the courses list. + * @return + */ + public CourseRun showCourseContent(String title) { + selenium.click("ui=learningResources::menu_courses()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + title + ")"); + selenium.waitForPageToLoad("30000"); + + return new CourseRun(selenium); + } + + /** + * Show the wiki content with this title. + * @param title + * @return + */ + public WikiRun showWikiContent(String title) { + selenium.click("ui=learningResources::menu_wikis()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isElementPresent("ui=commons::table_showAll()")) { + selenium.click("ui=commons::table_showAll()"); + selenium.waitForPageToLoad("30000"); + } + selenium.click("ui=learningResources::content_clickLearningResource(nameOfLearningResource=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new WikiRun(selenium); + } + + /** + * Shows the OLAT catalog view + * + * Click the Catalog entry on the left hand menu + * click it twice so the catalog is refreshed + * @return The Catalog object representing the OLAT catalog + */ + + public Catalog showCatalog(){ + selenium.click("ui=learningResources::menu_catalog()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::menu_catalog()"); + selenium.waitForPageToLoad("30000"); + return new Catalog(selenium); + } + + /** + * Imports a course with the given title only if there is no course with this title. + * Opens course editor and publish course. + * + * @param zippedCourse + * @param newTitleOfCourse + * @param newDescriptionOfCourse + * @return + * @throws InterruptedException + */ + public CourseEditor importCourse(File zippedCourse, String newTitleOfCourse, String newDescriptionOfCourse) throws InterruptedException { + // check if course with newTitleOfCourse exists + boolean checkIfExists = false; + LRDetailedView lRDetailedView = searchResource(newTitleOfCourse, null); + checkIfExists = lRDetailedView!=null; + + if (checkIfExists) { + System.out.println("Course with title " + newTitleOfCourse + " already exists, no need to import it!"); + return null; + } + + String remoteFile = Context.getContext().provideFileRemotely(zippedCourse); + + System.out.println("==================="); + System.out.println("Course Import Start"); + System.out.println(" Course: " + newTitleOfCourse); + System.out.println(" File: " + zippedCourse.getAbsolutePath()); + System.out.println(" Remote: " + remoteFile); + System.out.println("==================="); + + selenium.click("ui=learningResources::toolbox_import_course()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::courseImport_uploadFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::courseImport_fileChooser()",remoteFile); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("60000"); + + while (!selenium.isElementPresent("ui=learningResources::dialog_title()")) { + for (int second = 0;; second++) { + if (second >= 120) + break; + try { + if (selenium.isTextPresent("How do you wish to proceed?")) + break; + } catch (Exception e) { + } + Thread.sleep(500); + } + Thread.sleep(2000); + selenium.click("ui=learningResources::courseImport_importReferencesImport()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::courseImport_importReferencesContinue()"); + selenium.waitForPageToLoad("30000"); + } + // until the import is done + selenium.type("ui=learningResources::dialog_title()", newTitleOfCourse); + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", newDescriptionOfCourse); + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("60000"); + + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + + System.out.println("================="); + System.out.println("Course Import End"); + System.out.println("================="); + + CourseEditor courseEditor = new CourseEditor(selenium); + courseEditor.publishCourse(); + return courseEditor; + } + + /** + * Import CP and open CP editor. + * Attention: It could return null, if a resource with the same name already exists! Use unique names for resources!!! + * + * @param zippedResource + * @param newTitleOfCourse + * @param newDescriptionOfCourse + * @throws InterruptedException + */ + public CPResourceEditor importCP(File zippedResource, String newTitleOfCourse, String newDescriptionOfCourse) throws InterruptedException { + if(zippedResource==null) { + throw new IllegalArgumentException("zippedResource is null!!"); + } + boolean alreadyExists = checkIfExists(newTitleOfCourse); + if (alreadyExists) { + System.out.println("CP with title " + newTitleOfCourse + " already exists, no need to import it!"); + return null; + } + String remoteFile = Context.getContext().provideFileRemotely(zippedResource); + + selenium.click("ui=learningResources::toolbox_import_cpLearningContent()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::courseImport_uploadFile()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=learningResources::courseImport_fileChooser()",remoteFile); + selenium.click("ui=upload::submit()"); + selenium.waitForPageToLoad("60000"); + + selenium.type("ui=learningResources::dialog_title()", newTitleOfCourse); + selenium.click("ui=learningResources::dialog_description()"); + selenium.type("ui=learningResources::dialog_description()", newDescriptionOfCourse); + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::publishDialog_next()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + + return new CPResourceEditor(selenium,newTitleOfCourse); + } + + /** + * Check if resource exists. Returns true if found. + * @param title + * @return + */ + private boolean checkIfExists(String title) { + // check if resource with title exists + boolean checkIfExists = false; + LRDetailedView lRDetailedView = searchResource(title, null); + checkIfExists = lRDetailedView!=null; + + if (checkIfExists) { + return true; + } + return false; + } + + + /** + * Selects the courseIndex course in the next page, if desired, + * and returns a CourseRun if any found or null otherwise. + * + * @param selectNextPage + * @param courseIndex starts at 1. + * @return + */ + public CourseRun showCourseContent (boolean selectNextPage, int courseIndex) { + selectCoursesMenuItemOnce(); + + //select next page + if(selectNextPage && selenium.isElementPresent("ui=commons::table_selectNextPage()")) { + selenium.click("ui=commons::table_selectNextPage()"); + selenium.waitForPageToLoad("30000"); + } + + // select course in page + if(selenium.isElementPresent("ui=learningResources::content_courseTable_selectCourse(index=" + courseIndex + ")")) { + selenium.click("ui=learningResources::content_courseTable_selectCourse(index=" + courseIndex + ")"); + selenium.waitForPageToLoad("30000"); + return new CourseRun(selenium); + } + //no course found for the input values + return null; + } + + /** + * Select courses menu item ONLY if not already selected. + * Motivation: the implementation changed on 14.12.2010: + * Was: if the courses was on second page, + * it remained on the second page upon new selection. + * Now: each selection of courses leads to the first page. + * + */ + private void selectCoursesMenuItemOnce() { + if(!selenium.isElementPresent("ui=learningResources::menu_coursesMenuItemSelected()")) { + selenium.click("ui=learningResources::menu_courses()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * + * @return Returns true if the Forward button available. + */ + public boolean hasMorePages() { + return selenium.isElementPresent("ui=commons::table_selectNextPage()"); + } + + /** + * Creates CP resource. + * + * @param title + * @param description + * @return + */ + public CPResourceEditor createCPAndStartEditing(String title, String description) { + createResourceWithoutStartEdit(title, description, LR_Types.CP); + selenium.click("ui=learningResources::dialog_startYes()"); + selenium.waitForPageToLoad("30000"); + return new CPResourceEditor(selenium, title); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/PodcastResource.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/PodcastResource.java new file mode 100644 index 0000000000000000000000000000000000000000..839bd570d8a7caae9ddad489b1eda93b83706962 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/PodcastResource.java @@ -0,0 +1,118 @@ +package org.olat.test.util.selenium.olatapi.lr; + +import com.thoughtworks.selenium.Selenium; + +public class PodcastResource extends ResourceEditor { + + public PodcastResource(Selenium selenium, String title) { + super(selenium, title); + // TODO Auto-generated constructor stub + } + + /** + * + * @param title + * @param description + * @param imageName + */ + public void editPodcast(String title, String description, String imageName) { + selenium.click("ui=podcast::edit()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Description)", description); + + if(imageName!=null) { + //TODO: LD: add image + } + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * An episode requires an audio or video file that can be used with Flash. + * @param title + * @param description + * @param fileName + */ + public void createEpisode(String title, String description, String fileName) { + if(selenium.isElementPresent("ui=podcast::create()")) { + selenium.click("ui=podcast::create()"); + selenium.waitForPageToLoad("30000"); + } else if(selenium.isElementPresent("ui=podcast::addEpisode()")) { + selenium.click("ui=podcast::addEpisode()"); + selenium.waitForPageToLoad("30000"); + } + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + + editEpisodeForm(description, fileName); + } + + /** + * FIXME LD: this doesn't use the episode title! + * description or fileName could be null, if so they won't change. + * @param title + * @param description + * @param fileName + */ + public void editEpisode(String title, String description, String fileName) { + //selenium.click("ui=podcast::editEpisode(episodeTitle=" + title + ")"); + selenium.click("ui=podcast::editEpisode()"); + selenium.waitForPageToLoad("30000"); + + //we don't change the title + + //selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + editEpisodeForm(description, fileName); + } + + private void editEpisodeForm(String description, String fileName) { + if(description!=null) { + selenium.type("ui=commons::tinyMce_styledTextArea()", description); + } + + if(fileName!=null) { + //an episode requires an audio or video file that can be used with Flash. + selenium.type("ui=upload::fileChooser()", fileName); + sleepThread(5000); + } + + selenium.click("ui=commons::flexiForm_genericButton(buttonLabel=Publish)"); + selenium.waitForPageToLoad("30000"); + } + + public void commentEpisode(String title,String comment) { + selenium.click("ui=podcast::addComment(entryTitle=" + title + ")"); + selenium.waitForPageToLoad("30000"); + this.sleepThread(5000); + + //typeInRichText(comment); + selenium.selectFrame("//iframe[contains(@src,'javascript:\"\"')]"); + selenium.type("ui=commons::tinyMce_styledTextArea()", comment); + selenium.selectFrame("relative=top"); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::backLink()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean hasComments(String entryTitle, int num) { + return selenium.isTextPresent("Comments (" + num + ")"); + } + + public void includeExternal(String title, String description, String feedURL) { + selenium.click("ui=podcast::includeExternal()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + selenium.type("ui=commons::flexiForm_labeledTextArea(formElementLabel=Description)", description); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Feed URL)", feedURL); + + selenium.click("ui=commons::save()"); + selenium.waitForPageToLoad("30000"); + //TODO: LD: if no valid URL is provided, cancel or enter a new URL + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/lr/ResourceEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/lr/ResourceEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..b90618e793cd38a8fbff353f0679d0af31f8ec22 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/lr/ResourceEditor.java @@ -0,0 +1,55 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.lr; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Lavinia Dumitrescu + * + */ +public class ResourceEditor extends OLATSeleniumWrapper { + + private String resourceTitle; + + /** + * @param selenium + */ + public ResourceEditor(Selenium selenium, String title) { + super(selenium); + resourceTitle = title; + // TODO Auto-generated constructor stub + } + + /** + * TODO: works only if one resource open. + * @return + */ + public LRDetailedView close() { + //selenium.click("ui=tabs::closeNavTab()"); + selenium.click("ui=tabs::closeCourse(nameOfCourse=" + resourceTitle + ")"); + selenium.waitForPageToLoad("30000"); + return new LRDetailedView(selenium); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/package.html b/src/test/java/org/olat/test/util/selenium/olatapi/package.html new file mode 100644 index 0000000000000000000000000000000000000000..1d164d612024562cc117a12dc024a87d456f50f3 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/package.html @@ -0,0 +1,24 @@ +<html> +<head> +</head> + +<body> + +OLAT Abstraction Layer API. +<br/> +This represents a hierarchical object model (OLATSeleniumWrapper objects) of the +OLAT's sub-workflows, and encapsulates the selenium commands succession in an API. +The application layer classes are design based on the GUI pages structure. +The implementation status of this API reflects the current needs of the existing +tests (clients), that is only the minimum is implemented to fulfil the demands of +the tests cases. +<br/> +Another limitation of this API is that is role independent. +This means that the test developer has to keep in mind that the API is designed +from the administrator perspective. +<br/> +Ideally all tests cases should contain no selenium commands but only calls to the +Abstraction Layer API. + +</body> +</html> \ No newline at end of file diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPArtefactSearch.java b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPArtefactSearch.java new file mode 100644 index 0000000000000000000000000000000000000000..5cf5faeb88a03da6aa695ec9fe8daa287fb3d6b1 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPArtefactSearch.java @@ -0,0 +1,45 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.util.selenium.olatapi.portfolio; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * API wrapper for ePortfolio -> artefactview -> search-segment + * + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + */ +public class EPArtefactSearch extends OLATSeleniumWrapper { + + public EPArtefactSearch(Selenium selenium) { + super(selenium); + } + + public void toggleTextArtefactFilter(){ + if (selenium.isElementPresent("ui=epArtefactSearch::textartefact()")) { + selenium.click("ui=epArtefactSearch::textartefact()"); + selenium.waitForPageToLoad("30000"); + } + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPCollectWizard.java b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPCollectWizard.java new file mode 100644 index 0000000000000000000000000000000000000000..58b11715c300e7f1130b445e29af8efe4f153364 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPCollectWizard.java @@ -0,0 +1,110 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.util.selenium.olatapi.portfolio; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * + * abstraction for the ePortfolio artefact collect wizard + * possible steps in wizard are: + * 1. Inhalt erfassen + * 2. Metadaten erfassen + * 3. Tags angeben + * 4. Urheberrecht + * 5. Reflexion erfassen + * 6. Mappe auswählen + * not all of them are available depending on artefact-type + * + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + */ +public class EPCollectWizard extends OLATSeleniumWrapper { + + public EPCollectWizard(Selenium selenium) { + super(selenium); + } + + // wizzard to collect olat internal sources has 3 steps only as long as no map exists + public void filloutWizardForOLATSource(String title, String description) { + filloutStep2(title, description); + filloutStep3(); + filloutStep5(description); + } + + public void filloutWizardForTextArtefact(String content, String title, String description) { + // step 1: text content + selenium.type("ui=epCollectDialog::description()", content); + selenium.click("ui=commons::flexiForm_wizzard_next()"); + selenium.waitForPageToLoad("30000"); + filloutStep2(title, description); + filloutStep3(); + filloutStep4(); + filloutStep5(description); + } + + /** + * @param title + * @param description + */ + private void filloutStep2(String title, String description) { + // step 2: metadata + selenium.type("ui=epCollectDialog::title()", title); + selenium.type("ui=epCollectDialog::description()", description); + selenium.click("ui=commons::flexiForm_wizzard_next()"); + selenium.waitForPageToLoad("30000"); + } + + private void filloutStep3() { + // step 3: tagging + selenium.click("ui=epCollectDialog::taginput()"); + for (int i = 0; i < 3; i++) { + selenium.typeKeys("ui=epCollectDialog::taginput()", "test" + i); + sleepThread(3000); + if (selenium.isElementPresent("ui=epCollectDialog::taginputFeed()")) { + selenium.click("ui=epCollectDialog::taginputFeed()"); + } + } + selenium.click("ui=commons::flexiForm_wizzard_next()"); + selenium.waitForPageToLoad("30000"); + } + + private void filloutStep4() { + // step 4: check the copyright checkbox + selenium.check("ui=epCollectDialog::copyrightCheckbox()"); + selenium.click("ui=commons::flexiForm_wizzard_next()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * @param description represents the reflexion + */ + private void filloutStep5(String description) { + // step 5: reflexion and proceed with finishing wizard + selenium.type("ui=epCollectDialog::description()", "reflexion: " + description); + selenium.click("ui=commons::flexiForm_wizzard_finish()"); + selenium.waitForPageToLoad("30000"); + } + + + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPExtensions.java b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPExtensions.java new file mode 100644 index 0000000000000000000000000000000000000000..23d0eac604d0e8993a6a1fe27ddc5f62fc04f005 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPExtensions.java @@ -0,0 +1,96 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.util.selenium.olatapi.portfolio; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * API wrapper for ePortfolio Extensions + * also providing some helper methods. + * + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + */ +public class EPExtensions extends OLATSeleniumWrapper { + + public EPExtensions(Selenium selenium) { + super(selenium); + } + + public int getArtefactAmount(){ + // check the string containing amount of artefacts, if not present, or no artefact, return 0 + int amount = 0; + if (selenium.isElementPresent("ui=epArtefacts::artefactCount()")) { + String artCount = selenium.getText("ui=epArtefacts::artefactCount()"); + try { + amount = Integer.parseInt(artCount.split(":")[1].trim()); + } catch (Exception e) { + return amount; + } + } + return amount; + } + + public int getTotalArtefactAmount(){ + selenium.click("ui=epMenu::ePortfolioArtefacts()"); + selenium.waitForPageToLoad("30000"); + return getArtefactAmount(); + } + + + public EPCollectWizard createTextArtefactAndOpenWizard(){ + selenium.click("ui=epMenu::ePortfolioArtefacts()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=epArtefacts::addArtefactLink()"); + sleepThread(3000); + selenium.click("ui=epArtefacts::createTextArtefactLink()"); + selenium.waitForPageToLoad("30000"); + return new EPCollectWizard(selenium); + } + + public EPArtefactSearch getArtefactSearch(){ + selenium.click("ui=epArtefacts::artefactSearch()"); + selenium.waitForPageToLoad("30000"); + return new EPArtefactSearch(selenium); + } + + public EPMapEditor getMapEditor(){ + selenium.click("ui=epMenu::ePortfolioMyMaps()"); + selenium.waitForPageToLoad("30000"); + return new EPMapEditor(selenium); + } + + public void deleteFirstArtefact(){ + if (selenium.isElementPresent("ui=epArtefactSearch::deleteFirstArtefactLink()")){ + selenium.click("ui=epArtefactSearch::deleteFirstArtefactLink()"); + selenium.waitForPageToLoad("30000"); + sleepThread(6000); + selenium.click("ui=dialog::Yes()"); + sleepThread(1000); + } + } + + public boolean hasArtefact() { + return selenium.isElementPresent("ui=epArtefactSearch::deleteFirstArtefactLink()"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPMapEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPMapEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..949e157d5aa64a791c437f34a98deee0cb914373 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/portfolio/EPMapEditor.java @@ -0,0 +1,121 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) 2008 frentix GmbH, Switzerland<br> +* <p> +*/ + +package org.olat.test.util.selenium.olatapi.portfolio; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com + * + */ +public class EPMapEditor extends OLATSeleniumWrapper { + + public EPMapEditor(Selenium selenium) { + super(selenium); + } + + public void createDefaultMap(String title, String description){ + selenium.click("ui=epMap::addMapLink()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=epMap::createDefaultMap()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=epMap::createMapTitle()", title); + selenium.type("ui=epMap::createMapDescription()", description); + selenium.click("ui=epMap::createMapSaveButton()"); + } + + public void openMapByTitle(String title){ + selenium.click("ui=epMap::openMap(titleOfMap=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + + public void openFirstPage(){ + if (selenium.isElementPresent("ui=epMap::firstPageLink()")){ + selenium.click("ui=epMap::firstPageLink()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void addPages(int amount){ + for (int i = 0; i < amount; i++) { + selenium.click("ui=epMap::addPageLink()"); + selenium.waitForPageToLoad("30000"); + toggleEditMode(false); + } + } + + public void addStructures(int amount){ + for (int i = 0; i < amount; i++) { + selenium.click("ui=epMap::addStructLink()"); + selenium.waitForPageToLoad("30000"); + } + } + + public void toggleEditMode(boolean onOff){ + if (onOff){ + if (selenium.isElementPresent("ui=epMap::openEditor()")) + selenium.click("ui=epMap::openEditor()"); + } else { + if (selenium.isElementPresent("ui=epMap::closeEditor()")) + selenium.click("ui=epMap::closeEditor()"); + } + selenium.waitForPageToLoad("30000"); + } + + public void openShareDialogForMapByTitle(String title){ + selenium.click("ui=epMap::shareMap(titleOfMap=" + title + ")"); + selenium.waitForPageToLoad("30000"); + } + + public void shareToOtherUserWithName(String username){ + // add a rule + selenium.click("ui=epShare::createRule()"); + selenium.waitForPageToLoad("30000"); + // choose user + selenium.click("ui=epShare::nameInput()"); + selenium.typeKeys("ui=epShare::nameInput()", username); + sleepThread(3000); + if (selenium.isElementPresent("ui=epShare::nameInputSelect()")) { + selenium.click("ui=epShare::nameInputSelect()"); + } + // persist + selenium.click("ui=epShare::saveShare()"); + } + + public void changeElementTitleDescription(String title, String description){ + selenium.type("ui=epMapEditor::elTitle()", title); + selenium.type("ui=epMapEditor::elDescription()", description); + selenium.click("ui=epMapEditor::saveEditor()"); + selenium.waitForPageToLoad("30000"); + } + + public boolean deleteActiveTOCElement(){ + if (selenium.isElementPresent("ui=epMapEditor::deleteButton()")) { + selenium.click("ui=epMapEditor::deleteButton()"); + selenium.waitForPageToLoad("30000"); + return true; + } + return false; + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/EssayQuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/EssayQuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..6d4a7f5ce6677d0e8d692ce22b4433758996d371 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/EssayQuestionEditor.java @@ -0,0 +1,32 @@ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is an Text/Essay QuestionEditor, used only for Questionnaire. + * + * @author Lavinia Dumitrescu + * + */ +public class EssayQuestionEditor extends QuestionEditor { + + public EssayQuestionEditor(Selenium selenium) { + super(selenium); + // TODO Auto-generated constructor stub + } + + /** + * Set essay's answer lettersPerLine and numberOfLines, save. + * + * @param lettersPerLine + * @param numberOfLines + */ + public void setAnswerSize(int lettersPerLine, int numberOfLines) { + selectQuestionAndAnswersTab(); + selenium.type("ui=testEditor::content_questionAnswers_essayLettersPerLine()", String.valueOf(lettersPerLine)); + selenium.type("ui=testEditor::content_questionAnswers_essayNumberOfLines()", String.valueOf(numberOfLines)); + selenium.click("ui=commons::saveInput()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/FIBQuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/FIBQuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..abeedd878b3195d10fc28c6c7f7e75f524b86017 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/FIBQuestionEditor.java @@ -0,0 +1,101 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is a Gap-text or FILL-in-BLANK QuestionEditor with 2 modes: Test and Questionnaire. + * (The class might be splitted later in specific types.) + * <p> + * Used for tests/questionnaires editing. + * The Questionnaire functionality is a subset of the Test mode. + * + * @author Lavinia Dumitrescu + * + */ +public class FIBQuestionEditor extends QuestionEditor { + + /** + * @param selenium + */ + public FIBQuestionEditor(Selenium selenium) { + super(selenium); + } + + /** + * Adds new blank in the Question/answer tab of the selected GAP_TEXT question. + * + */ + public void addNewBlank() { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_addNewBlank()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Only for tests! + * Inserts the solution text in the blank field of the selected GAP_TEXT question. + * @param newText + * @param indexOfElement + */ + public void setBlankSolution(String newText, int indexOfElement) { + //TODO: implement parameter indexOfElement + selenium.type("ui=testEditor::content_questionAnswers_blankField(indexOfElement=" + String.valueOf(indexOfElement) + ")", newText); + selenium.click("ui=testEditor::content_questionAnswers_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Add new text fragment in the Question/answer tab of the selected GAP_TEXT question. + * + */ + public void addNewTextFragment() { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_addNewTextFragment()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Edit text element with the given index for the GAP_TEXT question type, while in Question/answers tab. + * @param index + * @param text + */ + public void editTextFragment(int index, String text) { + selenium.click("ui=testEditor::content_questionAnswers_editAnswerRest(indexOfAnswer=" + index + ")"); + selenium.waitForPageToLoad("30000"); + editRichText(text); + } + + /** + * Only for tests! + * Question/answer tab of the GAP_TEXT question type. + * + * @param elemIndex + */ + public void changeCapitalization(int elemIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_capitalization(indexOfElement=" + String.valueOf(elemIndex) + ")"); + selenium.click("ui=testEditor::content_questionAnswers_save()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/KPrimQuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/KPrimQuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..dded477c09ac0bcc08bad86c6791a9a90cb6fd0f --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/KPrimQuestionEditor.java @@ -0,0 +1,92 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is a KPrim QuestionEditor used only for tests editing. + * (The class might be splitted later in specific types.) + * + * @author Lavinia Dumitrescu + * + */ +public class KPrimQuestionEditor extends QuestionEditor { + + + /** + * @param selenium + */ + public KPrimQuestionEditor(Selenium selenium) { + super(selenium); + } + + + /** + * Edits the answer with the answerIndex for the selected KPRIM, + * while in Question/answers tab of the current selected question. + * The answerIndex must be greater that 0. + * @param newText + * @param answerIndex + */ + public void editAnswer(String newText, int answerIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_editAnswerKprim(indexOfAnswer=" + String.valueOf(answerIndex) + ")"); + selenium.waitForPageToLoad("30000"); + editRichText(newText); + } + + /** + * Chooses the correct solution for the current selected KPRIM question. + * + * @param firstCorrect + * @param secondCorrect + * @param thirdCorrect + * @param forthCorrect + */ + public void setCorrectKprimSolution(boolean firstCorrect, boolean secondCorrect, boolean thirdCorrect, boolean forthCorrect) { + selectQuestionAndAnswersTab(); + if(firstCorrect) { + selenium.click("ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=1)"); + }else { + selenium.click("ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=1)"); + } + if(secondCorrect) { + selenium.click("ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=2)"); + }else { + selenium.click("ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=2)"); + } + if(thirdCorrect) { + selenium.click("ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=3)"); + }else { + selenium.click("ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=3)"); + } + if(forthCorrect) { + selenium.click("ui=testEditor::content_questionAnswers_setCorrectKprim(indexOfAnswer=4)"); + }else { + selenium.click("ui=testEditor::content_questionAnswers_setIncorrectKprim(indexOfAnswer=4)"); + } + selenium.click("ui=testEditor::content_questionAnswers_save()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/MCQuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/MCQuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..004c629f0f98624886b342d964448e6a60285596 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/MCQuestionEditor.java @@ -0,0 +1,83 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is a Multiple choice QuestionEditor with 2 modes: Test and Questionnaire. + * (The class might be splitted later in specific types.) + * <p> + * Used for tests/questionnaires editing. + * The Questionnaire functionality is a subset of the Test mode. + * + * @author Lavinia Dumitrescu + * + */ +public class MCQuestionEditor extends QuestionEditor { + + + /** + * @param selenium + */ + public MCQuestionEditor(Selenium selenium) { + super(selenium); + } + + /** + * Adds new answer, while in Question/answers tab of the current selected question. + * + */ + public void addNewAnswer() { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_addNewAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + + /** + * Edits the answer with the answerIndex for the MULTIPLE_CHOICE, + * while in Question/answers tab of the current selected question. + * The answerIndex must be greater that 0. + * @param newText + * @param answerIndex + */ + public void editAnswer(String newText, int answerIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_editAnswerMc(indexOfAnswer=" + String.valueOf(answerIndex) + ")"); + selenium.waitForPageToLoad("30000"); + editRichText(newText); + } + + /** + * Only for tests! + * Selects the correct answer for the current selected MULTIPLE_CHOICE question. + * @param answerIndex + */ + public void setMultipleChoiceSolution(int answerIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_setCorrectMc(indexOfAnswer=" + answerIndex + ")"); + selenium.click("ui=testEditor::content_questionAnswers_save()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..98bf05c3684efc97e92b3246cc6fe1541fe29bde --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionEditor.java @@ -0,0 +1,94 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is a QuestionEditor. The class might be splitted later in specific types. + * + * @author Lavinia Dumitrescu + * + */ +public class QuestionEditor extends OLATSeleniumWrapper { + + //supported question types + public enum QUESTION_TYPES {SINGLE_CHOICE, MULTIPLE_CHOICE, KPRIM, GAP_TEXT, ESSAY} + + /** + * @param selenium + */ + public QuestionEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isTextPresent("Meta data")) { + throw new IllegalStateException("This is not the - Question Editor- page"); + } + } + + /** + * Change question title to newTitle, in Meta data tab. + * @param currentTitle + * @param newTitle + */ + public void setQuestionTitle(String newTitle) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", newTitle); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + + /** + * Select question with the given title and then the Question/answers tab. + * @param title + */ + public void selectQuestionAndAnswersTab() { + if(selenium.isElementPresent("ui=testEditor::content_questionAnswers_tabQuestionAnswers()")) { + selenium.click("ui=testEditor::content_questionAnswers_tabQuestionAnswers()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Edit question, while in Question/answers tab of the current selected question of the types: + * SINGLE_CHOICE, MULTIPLE_CHOICE or KPRIM. + * + * @param newText + */ + public void editQuestion(String newText) { + selenium.click("ui=testEditor::content_questionAnswers_editQuestion()"); + selenium.waitForPageToLoad("30000"); + + editRichText(newText); + } + + protected void editRichText(String text) { + // the description shows up in an iframe + typeInRichText(text); + selenium.click("ui=commons::flexiForm_saveButtonVertical()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionnaireEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionnaireEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..944d92cb0b5950cfc6382837a817cac159e0b403 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/QuestionnaireEditor.java @@ -0,0 +1,75 @@ +package org.olat.test.util.selenium.olatapi.qti; + +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor.QUESTION_TYPES; + +import com.thoughtworks.selenium.Selenium; + +/** + * Subclass of the TestEditor. + * It allows to add section nodes or question nodes of the type: SINGLE_CHOICE, MULTIPLE_CHOICE, GAP_TEXT, and ESSAY. + * It offers an EssayQuestionEditor more than the TestEditor. + * + * @author Lavinia Dumitrescu + * + */ +public class QuestionnaireEditor extends TestEditor { + + public QuestionnaireEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=testEditor::toolbox_add_addText()")) { + //it must have an add Text link + throw new IllegalStateException("This is not the - QuestionnaireEditor - page"); + } + } + + /** + * QUESTION_TYPES: SINGLE_CHOICE, MULTIPLE_CHOICE, GAP_TEXT, and ESSAY. + */ + protected void clickAddQuestion(QUESTION_TYPES type) { + if(QUESTION_TYPES.SINGLE_CHOICE.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addSingleChoice()"); + } else if(QUESTION_TYPES.MULTIPLE_CHOICE.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addMultipleChoice()"); + } else if(QUESTION_TYPES.GAP_TEXT.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addGapText()"); + } else if(QUESTION_TYPES.ESSAY.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addText()"); + } + } + + /** + * QUESTION_TYPES: SINGLE_CHOICE, MULTIPLE_CHOICE, GAP_TEXT, and ESSAY. + */ + protected QuestionEditor returnQuestionEditor(QUESTION_TYPES type) { + if(QUESTION_TYPES.SINGLE_CHOICE.equals(type)) { + return new SCQuestionEditor(selenium); + } else if(QUESTION_TYPES.MULTIPLE_CHOICE.equals(type)) { + return new MCQuestionEditor(selenium); + } else if(QUESTION_TYPES.GAP_TEXT.equals(type)) { + return new FIBQuestionEditor(selenium); + } else if(QUESTION_TYPES.ESSAY.equals(type)) { + return new EssayQuestionEditor(selenium); + } + return new QuestionEditor(selenium); + } + + /** + * Checks the question type. + * QUESTION_TYPES: SINGLE_CHOICE, MULTIPLE_CHOICE, GAP_TEXT, and ESSAY. + * @return Returns null if no question type identified. + */ + protected QuestionEditor getCurrentQuestion() { + if(selenium.isElementPresent("ui=testEditor::content_metadata_scType()")) { + return new SCQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_mcType()")) { + return new MCQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_gapType()")) { + return new FIBQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_essayType()")) { + return new EssayQuestionEditor(selenium); + } + throw new IllegalStateException("This is not a - QuestionEditor - page!"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/SCQuestionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/SCQuestionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..4ee65cd2ec8d5645ac41f0b05b5a1fbd3d7d3789 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/SCQuestionEditor.java @@ -0,0 +1,82 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +/** + * This is a Single choice QuestionEditor with 2 modes: Test and Questionnaire. + * (The class might be splitted later in specific types.) + * <p> + * Used for tests/questionnaires editing. + * The Questionnaire functionality is a subset of the Test mode. + * + * @author Lavinia Dumitrescu + * + */ +public class SCQuestionEditor extends QuestionEditor { + + /** + * @param selenium + */ + public SCQuestionEditor(Selenium selenium) { + super(selenium); + } + + /** + * Adds new answer, while in Question/answers tab of the current SINGLE_CHOICE question. + * + */ + public void addNewAnswer() { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_addNewAnswer()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Edits the answer with the answerIndex for the selected SINGLE_CHOICE + * while in Question/answers tab of the current selected question. + * The answerIndex must be greater that 0. + * @param newText + * @param answerIndex + */ + public void editAnswer(String newText, int answerIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_editAnswerRest(indexOfAnswer=" + String.valueOf(answerIndex) + ")"); + selenium.waitForPageToLoad("30000"); + editRichText(newText); + } + + + /** + * Only for tests! This SHOULD NOT be called for a questionnaire editor.! + * Selects the correct answer for the current selected SINGLE_CHOICE question. + * + * @param answerIndex + */ + public void setSingleChoiceSolution(int answerIndex) { + selectQuestionAndAnswersTab(); + selenium.click("ui=testEditor::content_questionAnswers_setCorrectSc(indexOfAnswer=" + String.valueOf(answerIndex) + ")"); + selenium.click("ui=testEditor::content_questionAnswers_save()"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/SectionEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/SectionEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..7d97c44a894c7bfc507b7212e54131d1437eeaab --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/SectionEditor.java @@ -0,0 +1,58 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * @author Lavinia Dumitrescu + * + */ +public class SectionEditor extends OLATSeleniumWrapper { + + /** + * @param selenium + */ + public SectionEditor(Selenium selenium) { + super(selenium); + + // Check that we're on the right place + if(!selenium.isElementPresent("ui=testEditor::content_section_orderOfQuestions()")) { + throw new IllegalStateException("This is not the - Test Section - page"); + } + } + + /** + * Selects section with the currentTitle and change title to newTitle. + * @param currentTitle + * @param newTitle + */ + public void setSectionTitle(String currentTitle, String newTitle) { + selenium.click("ui=testEditor::content_section_title()"); + selenium.type("ui=testEditor::content_section_title()", newTitle); + selenium.click("ui=testEditor::content_section_save()"); + selenium.waitForPageToLoad("30000"); + } + +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/qti/TestEditor.java b/src/test/java/org/olat/test/util/selenium/olatapi/qti/TestEditor.java new file mode 100644 index 0000000000000000000000000000000000000000..96057b21b8f3b6851f971ce4638fdcb5afd4e5b6 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/qti/TestEditor.java @@ -0,0 +1,238 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, + * <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) 1999-2007 at Multimedia- & E-Learning Services (MELS),<br> + * University of Zurich, Switzerland. + * <p> + */ +package org.olat.test.util.selenium.olatapi.qti; + +import com.thoughtworks.selenium.Selenium; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.olatapi.lr.LRDetailedView; +import org.olat.test.util.selenium.olatapi.qti.QuestionEditor.QUESTION_TYPES; + +/** + * This is the TestEditor abstraction. <p> + * It allows to add section nodes or question nodes of the type: SINGLE_CHOICE, MULTIPLE_CHOICE, KPRIM, GAP_TEXT. + * + * @author Lavinia Dumitrescu + * + */ +public class TestEditor extends OLATSeleniumWrapper { + + + + /** + * @param selenium + */ + public TestEditor(Selenium selenium) { + super(selenium); + + //Check that we're on the right place + if(!selenium.isElementPresent("ui=testEditor::toolbox_add_addSection()")) { + //it must have an Add Section link. + throw new IllegalStateException("This is not the - Test editor - page"); + } + } + + /** + * Close editor and save changes. + * @return + */ + public LRDetailedView close() { + selenium.click("ui=testEditor::toolbox_editorTools_closeEditor()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=testEditor::dialog_clickSave()"); + selenium.waitForPageToLoad("30000"); + + return new LRDetailedView(selenium); + } + + /** + * Sets the passing score for the curent test. + * @param score + */ + public void setNecessaryPassingScore(double score) { + selenium.type("ui=testEditor::content_test_necessaryPassingScore()", String.valueOf(score)); + selenium.click("ui=testEditor::content_test_save()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Adds question of the specified type with the given title. + * @param type + * @param title + */ + public QuestionEditor addQuestion(QUESTION_TYPES type, String title) { + clickAddQuestion(type); + + selenium.waitForPageToLoad("30000"); + selenium.click("ui=testEditor::toolbox_add_insertAsRootsFirstChild()"); + selenium.click("ui=testEditor::toolbox_add_save()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", title); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + + return returnQuestionEditor(type); + } + + /** + * QUESTION_TYPES: SINGLE_CHOICE, MULTIPLE_CHOICE, KPRIM, GAP_TEXT + * @param type + */ + protected void clickAddQuestion(QUESTION_TYPES type) { + if(QUESTION_TYPES.SINGLE_CHOICE.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addSingleChoice()"); + } else if(QUESTION_TYPES.MULTIPLE_CHOICE.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addMultipleChoice()"); + } else if(QUESTION_TYPES.KPRIM.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addKprim()"); + } else if(QUESTION_TYPES.GAP_TEXT.equals(type)) { + selenium.click("ui=testEditor::toolbox_add_addGapText()"); + } + } + + /** + * + * @param type + * @return Returns a SCQuestionEditor, MCQuestionEditor, KPrimQuestionEditor or a FIBQuestionEditor. + */ + protected QuestionEditor returnQuestionEditor(QUESTION_TYPES type) { + if(QUESTION_TYPES.SINGLE_CHOICE.equals(type)) { + return new SCQuestionEditor(selenium); + } else if(QUESTION_TYPES.MULTIPLE_CHOICE.equals(type)) { + return new MCQuestionEditor(selenium); + } else if(QUESTION_TYPES.KPRIM.equals(type)) { + return new KPrimQuestionEditor(selenium); + } else if(QUESTION_TYPES.GAP_TEXT.equals(type)) { + return new FIBQuestionEditor(selenium); + } + return new QuestionEditor(selenium); + } + + /** + * Adds new section with the specified title. + * @param title + */ + public SectionEditor addSection(String title) { + selenium.click("ui=testEditor::toolbox_add_addSection()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + selenium.click("ui=testEditor::toolbox_add_save()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=testEditor::content_section_title()"); + selenium.type("ui=testEditor::content_section_title()", title); + selenium.click("ui=testEditor::content_section_save()"); + selenium.waitForPageToLoad("30000"); + return new SectionEditor(selenium); + } + + /** + * Select question with the given title. + * @param title + */ + public QuestionEditor selectQuestion(String title) { + selenium.click("ui=testEditor::menu_link(link=" + title + ")"); + selenium.waitForPageToLoad("30000"); + + return getCurrentQuestion(); + } + + /** + * Checks the question type. + * QUESTION_TYPES: SINGLE_CHOICE, MULTIPLE_CHOICE, KPRIM, GAP_TEXT + * @return Returns null if no question type identified. + */ + protected QuestionEditor getCurrentQuestion() { + if(selenium.isElementPresent("ui=testEditor::content_metadata_scType()")) { + return new SCQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_mcType()")) { + return new MCQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_gapType()")) { + return new FIBQuestionEditor(selenium); + } else if(selenium.isElementPresent("ui=testEditor::content_metadata_kprimType()")) { + return new KPrimQuestionEditor(selenium); + } + throw new IllegalStateException("This is not a - QuestionEditor - page!"); + } + + public SectionEditor selectSection(String title) { + selenium.click("ui=testEditor::menu_link(link=" + title + ")"); + selenium.waitForPageToLoad("30000"); + return new SectionEditor(selenium); + } + + /** + * Deletes the current selected node. + * + */ + public void deleteCurrentNode(boolean confirmDeletion) { + selenium.click("ui=testEditor::toolbox_Change_changeDelete()"); + selenium.waitForPageToLoad("30000"); + if(confirmDeletion) { + selenium.click("ui=testEditor::dialog_clickYes()"); + selenium.waitForPageToLoad("30000"); + } + } + + /** + * Try to delete the current selected section/question node but not possible. + * A Test must contain at least a section node. + * @throws Exception + */ + public void deleteUndeleteable(boolean isSection) throws Exception { + String cannotBeDeteledMsg = "Section cannot be deleted."; + if(!isSection) { + cannotBeDeteledMsg = "Question cannot be deleted."; + } + selenium.click("ui=testEditor::toolbox_Change_changeDelete()"); + selenium.waitForPageToLoad("30000"); + for (int second = 0;; second++) { + if (second >= 60) fail("timeout"); + try { if (selenium.isTextPresent(cannotBeDeteledMsg)) break; } catch (Exception e) {} + Thread.sleep(1000); + } + selenium.click("ui=testEditor::dialog_clickOk()"); + } + + /** + * Copy the current selected node and sets the newTitle as title. + * @param newTitle + */ + public QuestionEditor copyCurrentQuestion(String newTitle) { + selenium.click("ui=testEditor::toolbox_Change_changeCopy()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=courseEditor::toolbox_insertCourseElements_insertAsRootsFirstChild()"); + selenium.click("ui=testEditor::toolbox_add_save()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Title)", newTitle); + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + return new QuestionEditor(selenium); + } + + /** + * Clicks OK on a dialog. + * + */ + public void dialogOK() { + selenium.click("ui=testEditor::dialog_clickOk()"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/user/UserManagement.java b/src/test/java/org/olat/test/util/selenium/olatapi/user/UserManagement.java new file mode 100644 index 0000000000000000000000000000000000000000..5c45ff5bea4450ae5f0ffb5488292dfa22ba04c2 --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/user/UserManagement.java @@ -0,0 +1,258 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.user; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; +import org.olat.test.util.selenium.SeleniumHelper; + +import com.thoughtworks.selenium.Selenium; + +/** + * UserManagement abstraction. + * + * @author Lavinia Dumitrescu + * + */ +public class UserManagement extends OLATSeleniumWrapper { + + public UserManagement(Selenium selenium) { + super(selenium); + try { //loads slower since 29.01.2010 + Thread.sleep(5000); + } catch (Exception e) { + // nothing to do + } + // Check that we're on the right place + if(!selenium.isElementPresent("ui=userManagement::menu_userSearch()")) { + throw new IllegalStateException("This is not the - UserManagement - page"); + } + } + + /** + * + * @param username + * @return Returns false if none found, else true if at least one found. + */ + public boolean searchUser(String username) { + selectUserSearch(); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + if(selenium.isTextPresent("No user was found with these attributes")) { + return false; + } else if (selenium.isElementPresent("ui=commons::usertable_userlist_selectAll()")) { + return true; + } + throw new IllegalStateException("The searchUser could not decide whether it find or not any user!"); + } + + /** + * Search and selects user + * @param username + * @return + */ + public UserSettings selectUser(String username) { + boolean userFound = searchUser(username); + if(userFound) { + selenium.click("ui=commons::usertable_userlist_selectUserName(nameOfUser=" + username + ")"); + selenium.waitForPageToLoad("30000"); + + return new UserSettings(selenium); + } + throw new IllegalStateException("selectUser could not find any user!"); + } + + /** + * Checks that one cannot edit admin users. + * @param username + * @return Returns true if cannotEditUser message shows up + */ + public boolean cannotEditUser(String username) throws Exception { + boolean userFound = searchUser(username); + if(userFound) { + selenium.click("ui=commons::usertable_userlist_selectUserName(nameOfUser=" + username + ")"); + selenium.waitForPageToLoad("30000"); + return SeleniumHelper.isTextPresent(selenium, "You do not have enough rights to edit this user.", 20); + } + throw new IllegalStateException("cannotEditUser could not find any user!"); + } + + /** + * Select the search user menu item. + */ + private void selectUserSearch() { + selenium.click("ui=userManagement::menu_userSearch()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Creates user without check whether already exists. + * Language: EN. + * Should this check if user exists? + * @param username + * @param firstname + * @param lastname + * @param email + * @param password + */ + public UserSettings createUser(String username, String firstname, String lastname, String email, String password) { + selenium.click("ui=userManagement::menu_createUser()"); + selenium.waitForPageToLoad("30000"); + + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=First name)", firstname); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=Last name)", lastname); + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=E-mail)", email); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=Password)", password); + //select EN + selenium.select("ui=userManagement::content_createUser_language()", "value=en"); + selenium.type("ui=commons::flexiForm_labeledPasswordInput(formElementLabel=Verify password)", password); + selenium.click("ui=userManagement::content_createUser_save()"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(5000); + } catch (Exception e) { + // nothing to do + } + assertTrue(selenium.isTextPresent("Manage user settings")); + return new UserSettings(selenium); + } + + /** + * Imports users, the parameter is a excel like string, see the GUI example. + * Imports only the new users. If at least one imported (new) returns true, else false. + * + * @param rowsFromExcelString + * @return Returns true if all users could be imported. + */ + public boolean importAllUsers(String rowsFromExcelString) { + startImportUsersWizard(rowsFromExcelString); + + //if at least one new user, the finish button is active + if(selenium.isElementPresent("ui=userManagement::content_importUsers_finish()") && !selenium.isElementPresent("ui=userManagement::content_importUsers_importWarnIcon()")) { + selenium.click("ui=userManagement::content_importUsers_finish()"); + selenium.waitForPageToLoad("30000"); + //TODO:LD: add assert if user created: "New users successfully created!" ??? here? + //SeleniumHelper.waitUntilTextPresent(selenium, "New users successfully created!", 60); + return true; + } + return false; + } + + private void startImportUsersWizard(String rowsFromExcelString) { + selenium.click("ui=userManagement::menu_importUsers()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=userManagement::content_importUsers_startUserImport()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=userManagement::content_importUsers_fillTextArea()", rowsFromExcelString); + selenium.click("ui=userManagement::content_importUsers_next()"); + selenium.waitForPageToLoad("30000"); + assertTrue(selenium.isTextPresent("Preview of user data")); + } + + /** + * Imports only the new users from the rowsFromExcelString. + * It checks that there are already existing users in the input data set. + * + * @param rowsFromExcelString + * @return Returns true if at least one user could be imported. + */ + public boolean importOnlyNewUsers(String rowsFromExcelString) { + startImportUsersWizard(rowsFromExcelString); + + if(selenium.isElementPresent("ui=userManagement::content_importUsers_finish()") && selenium.isElementPresent("ui=userManagement::content_importUsers_importWarnIcon()")) { + selenium.click("ui=userManagement::content_importUsers_finish()"); + selenium.waitForPageToLoad("30000"); + //TODO:LD: add assert if user created: "New users successfully created!" ??? here? + return true; + } + return false; + } + + /** + * Tries to import but no new users found. + * @param rowsFromExcelString + * @return Returns true if no new user found for import. + */ + public boolean importUsersExpectingError(String rowsFromExcelString) { + startImportUsersWizard(rowsFromExcelString); + + if(!selenium.isElementPresent("ui=userManagement::content_importUsers_finish()")) { + assertTrue(selenium.isTextPresent("There are no new users in this table.")); + selenium.click("ui=userManagement::content_importUsers_cancel()"); + selenium.waitForPageToLoad("30000"); + return true; + } + return false; + } + + public void deleteUser(String username) { + selenium.click("ui=userManagement::menu_deleteUser()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_checkUsernameToRemove(nameOfUser=" + username + ")"); + selenium.click("ui=commons::usertable_sendUserDeletionEmail()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=commons::usertable_adduser_finish()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Deletes user if the user deletion workflow is not locked and if a user is found. + * It assumes that a user identified by username exists, so call searchUser beforehand. + * @param username + * @return Returns true only if the user was deleted. + */ + public boolean deleteUserImmediately(String username) { + selenium.click("ui=userManagement::menu_deleteUserImmediately()"); + selenium.waitForPageToLoad("30000"); + if(selenium.isTextPresent("The workflow regarding the deletion of users is being edited by")) { + //workflow locked, cannot delete user + return false; + } else if(selenium.isElementPresent("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)")) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=User name)", username); + selenium.click("ui=commons::flexiForm_genericLink(buttonLabel=Search)"); + selenium.waitForPageToLoad("30000"); + try { + Thread.sleep(1000); + } catch (Exception e) { + // nothing to do + } + if(selenium.isTextPresent("No user was found with these attributes. Please try again.")) { + throw new IllegalStateException("deleteUserImmediately could not find any user!"); + } + selenium.click("ui=commons::usertable_adduser_checkUsername(nameOfUser=" + username + ")"); + selenium.click("ui=commons::usertable_adduser_choose()"); + selenium.waitForPageToLoad("30000"); + selenium.click("ui=dialog::Okay()"); + selenium.waitForPageToLoad("90000");// looks like sometimes user delete takes rather long. increasing timeout to 90sec from 30sec + return true; + } + throw new IllegalStateException("deleteUserImmediately found a strange state: delete workflow is not locked but it doesn't find the delete form either!"); + } + + public void setUsersReplayURL(String usersNamesInSeparateLines) { + selenium.click("ui=userManagement::menu_usersReplayURL()"); + selenium.waitForPageToLoad("30000"); + selenium.type("ui=userManagement::content_usersReplayURL_userReplayTextArea()", usersNamesInSeparateLines); + selenium.click("ui=commons::saveInput()"); + selenium.waitForPageToLoad("30000"); + } +} diff --git a/src/test/java/org/olat/test/util/selenium/olatapi/user/UserSettings.java b/src/test/java/org/olat/test/util/selenium/olatapi/user/UserSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..410965628c5b40c9ac380bcc2a9129a0d571ca3f --- /dev/null +++ b/src/test/java/org/olat/test/util/selenium/olatapi/user/UserSettings.java @@ -0,0 +1,164 @@ +/** +* OLAT - Online Learning and Training<br> +* http://www.olat.org +* <p> +* Licensed under the Apache License, Version 2.0 (the "License"); <br> +* you may not use this file except in compliance with the License.<br> +* You may obtain a copy of the License at +* <p> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p> +* Unless required by applicable law or agreed to in writing,<br> +* software distributed under the License is distributed on an "AS IS" BASIS, <br> +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> +* See the License for the specific language governing permissions and <br> +* limitations under the License. +* <p> +* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> +* University of Zurich, Switzerland. +* <p> +*/ +package org.olat.test.util.selenium.olatapi.user; + +import org.olat.test.util.selenium.olatapi.OLATSeleniumWrapper; + +import com.thoughtworks.selenium.Selenium; + +/** + * UserManagement/UserSettings abstraction. + * + * @author Lavinia Dumitrescu + * + */ +public class UserSettings extends OLATSeleniumWrapper { + + public UserSettings(Selenium selenium) { + super(selenium); + + if(!selenium.isElementPresent("ui=userManagement::content_userdetail_roles()")) { + throw new IllegalStateException("This is not the - UserSettings - page"); + } + } + + /** + * Sets the first name and/or the visibility of it. + * @param firstname, could be null if the change is not desired. + * @param showOnVisitingCard, could be null if the change is not desired. + */ + public void setFirstName(String firstname, Boolean showOnVisitingCard) { + selectUserProfileTab(); + setTextInput("First name", firstname, showOnVisitingCard); + } + + private void setTextInput(String inputLabel, String text, Boolean showOnVisitingCard) { + if(text!=null) { + selenium.type("ui=commons::flexiForm_labeledTextInput(formElementLabel=" + inputLabel + ")", text); + } + if(showOnVisitingCard!=null) { + if(showOnVisitingCard) { + selenium.check("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } else { + selenium.uncheck("ui=commons::flexiForm_labeledCheckbox(formElementLabel=" + inputLabel + ")"); + } + } + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + public void setLastName(String lastname, Boolean showOnVisitingCard) { + selectUserProfileTab(); + setTextInput("Last name", lastname, showOnVisitingCard); + } + + public void setEmail(String email, Boolean showOnVisitingCard) { + selectUserProfileTab(); + setTextInput("E-mail address", email, showOnVisitingCard); + } + + public String getEmail() { + selectUserProfileTab(); + return selenium.getValue("ui=commons::flexiForm_labeledTextInput(formElementLabel=E-mail)"); + } + + public void setPassword(String newPassword) { + selectChangePasswordTab(); + selenium.type("ui=userManagement::content_userdetail_changePasswordTab_newPassword()", newPassword); + selenium.type("ui=userManagement::content_userdetail_changePasswordTab_confirmPassword()", newPassword); + + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + private void selectChangePasswordTab() { + selenium.click("ui=userManagement::content_userdetail_changePassword()"); + selenium.waitForPageToLoad("30000"); + } + + /** + * Sets users roles. + * If a parameter is null, the role state doesn't change. + * + * @param isUserManager, if null, no change, else on/off accordingly with the boolean value. + * @param isGroupManager + * @param isAuthor + * @param isSysAdmin + * @param isLearningResourceAdmin + */ + public void setRoles(Boolean isUserManager, Boolean isGroupManager, Boolean isAuthor, + Boolean isSysAdmin, Boolean isLearningResourceAdmin) { + + selectRolesTab(); + if (isUserManager != null) { + if (isUserManager) { + selenium.check("ui=userManagement::content_userdetail_roles_isUsermanager()"); + } else { + selenium.uncheck("ui=userManagement::content_userdetail_roles_isUsermanager()"); + } + } + if (isGroupManager != null) { + if (isGroupManager) { + selenium.check("ui=userManagement::content_userdetail_roles_isGroupmanager()"); + } else { + selenium.uncheck("ui=userManagement::content_userdetail_roles_isGroupmanager()"); + } + } + if (isAuthor != null) { + if (isAuthor) { + selenium.check("ui=userManagement::content_userdetail_roles_isAuthor()"); + } else { + selenium.uncheck("ui=userManagement::content_userdetail_roles_isAuthor()"); + } + } + if (isSysAdmin != null) { + if (isSysAdmin) { + selenium.check("ui=userManagement::content_userdetail_roles_isAdmin()"); + } else { + selenium.uncheck("ui=userManagement::content_userdetail_roles_isAdmin()"); + } + } + if (isLearningResourceAdmin != null) { + if (isLearningResourceAdmin) { + selenium.check("ui=userManagement::content_userdetail_roles_isLearningResourceManager()"); + } else { + selenium.uncheck("ui=userManagement::content_userdetail_roles_isLearningResourceManager()"); + } + } + + selenium.click("ui=commons::flexiForm_saveButton()"); + selenium.waitForPageToLoad("30000"); + } + + private void selectRolesTab() { + if(selenium.isElementPresent("ui=userManagement::content_userdetail_roles()")) { + selenium.click("ui=userManagement::content_userdetail_roles()"); + selenium.waitForPageToLoad("30000"); + } + } + + private void selectUserProfileTab() { + if(selenium.isElementPresent("ui=userManagement::content_userdetail_userProfile()")) { + selenium.click("ui=userManagement::content_userdetail_roles()"); + selenium.waitForPageToLoad("30000"); + } + } +} diff --git a/src/test/java/org/olat/test/util/setup/OlatLoginInfos.java b/src/test/java/org/olat/test/util/setup/OlatLoginInfos.java new file mode 100644 index 0000000000000000000000000000000000000000..7afb09309fcf9510c7d7a7b9526147598f263ef8 --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/OlatLoginInfos.java @@ -0,0 +1,76 @@ +package org.olat.test.util.setup; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Simple wrapper object around login information + * to log into OLAT. + * <p> + * The information provided here should be sufficient to + * create a selenium session with it and log into OLAT. + * Hence we need the hostname of the selenium server + * and the hostname + login details of the OLAT server. + * @author Stefan + * + */ +public class OlatLoginInfos { + + private final String seleniumHostname_; + private final String seleniumBrowserId_; + private final URL fullOlatServerUrl_; + private final String username_; + private final String password_; + + public OlatLoginInfos(String seleniumHostname, String seleniumBrowserId, + String fullOlatServerUrl, String username, String password) throws MalformedURLException { + if (isNullOrEmpty(seleniumHostname)) { + throw new IllegalArgumentException("seleniumHostname is null or empty"); + } + if (isNullOrEmpty(seleniumBrowserId)) { + throw new IllegalArgumentException("seleniumBrowserId is null or empty"); + } + if (isNullOrEmpty(fullOlatServerUrl)) { + throw new IllegalArgumentException("fullOlatServerUrl is null or empty"); + } + if (isNullOrEmpty(username)) { + throw new IllegalArgumentException("username is null or empty"); + } + if (isNullOrEmpty(password)) { + throw new IllegalArgumentException("password is null or empty"); + } + seleniumHostname_ = seleniumHostname; + seleniumBrowserId_ = seleniumBrowserId; + fullOlatServerUrl_ = new URL(fullOlatServerUrl); + username_ = username; + password_ = password; + } + + private boolean isNullOrEmpty(String param) { + return param==null || param.length()==0; + } + + public String getSeleniumHostname() { + return seleniumHostname_; + } + + public String getSeleniumBrowserId() { + return seleniumBrowserId_; + } + + public String getFullOlatServerUrl() { + return fullOlatServerUrl_.toExternalForm(); + } + + public String getUsername() { + return username_; + } + + public String getPassword() { + return password_; + } + + public String getLanguage() { + return "English"; + } +} diff --git a/src/test/java/org/olat/test/util/setup/SetupType.java b/src/test/java/org/olat/test/util/setup/SetupType.java new file mode 100644 index 0000000000000000000000000000000000000000..371d06924f764b06f12999dfb65a9a1fb6b7c98b --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/SetupType.java @@ -0,0 +1,32 @@ +package org.olat.test.util.setup; + +/** + * Originally the test author could choose from a list of possible + * setups, but later there was only one setup type used: TWO_NODE_CLUSTER. <br/> + * It was decided that it would be wiser to run all tests with the same setup. + * + * @author lavinia + * + */ +public enum SetupType { + + /** @deprecated not supported anymore */ + CLEAN_AND_RESTARTED_SINGLE_VM, + /** @deprecated not supported anymore */ + CLEAN_AND_RESTARTED_TWO_NODE_CLUSTER, + /** @deprecated not supported anymore */ + RESTARTED_SINGLE_VM, + /** @deprecated not supported anymore */ + RESTARTED_TWO_NODE_CLUSTER, + /** @deprecated not supported anymore */ + SINGLE_VM, + TWO_NODE_CLUSTER; + + /** @deprecated not supported anymore */ + public boolean isSingleVm() { + if (this==CLEAN_AND_RESTARTED_SINGLE_VM) return true; + if (this==RESTARTED_SINGLE_VM) return true; + if (this==SINGLE_VM) return true; + return false; + } +} diff --git a/src/test/java/org/olat/test/util/setup/context/Context.java b/src/test/java/org/olat/test/util/setup/context/Context.java new file mode 100644 index 0000000000000000000000000000000000000000..e56370ca1edb6e4c950e9186e369e7a92d4754e4 --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/context/Context.java @@ -0,0 +1,516 @@ +package org.olat.test.util.setup.context; + +import java.io.File; +import java.net.MalformedURLException; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import junit.framework.AssertionFailedError; + +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.SeleniumManager; +import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper; +import org.olat.test.util.selenium.olatapi.WorkflowHelper; +import org.olat.test.util.setup.OlatLoginInfos; +import org.olat.test.util.setup.SetupType; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointRef; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import com.thoughtworks.selenium.Selenium; + +/** + * Setups the context for running selenium tests. <br/> + * Configurable via customcontext.xml if any available, else via defaultcontext.xml + * + * @author eglis + * + */ +public abstract class Context { + + public static InheritableThreadLocal<Context> currentContext=new InheritableThreadLocal<Context>(); + + private static Map<SetupType,Context> contexts_; + protected final static String log4JConfigFilenameKey = "log4jConfigFilename"; + protected boolean cleanupBeforeTest = true; //should be read from context? + public static String FILE_RESOURCES_PATH = "org/olat/test/file_resources/"; + public static String DEMO_COURSE_NAME_1 = "OLAT: Demo course"; + public static String DEMO_COURSE_NAME_2 = "OLAT: Demo course"; + public static String DEMO_COURSE_NAME_3 = "OLAT: Demokurs Einschreibung"; + + + static { + System.out.println(new Date()); + System.out.println("INITIALIZING SPRING WITH contexts.xml FOR SELENIUMTESTS' CONTEXT..."); + contexts_ = new HashMap<SetupType,Context>(); + new ClassPathXmlApplicationContext( + new String[] { + "classpath*:customcontext.xml" + }); + if (contexts_.size()==0) { + new ClassPathXmlApplicationContext( + new String[] { + "classpath*:defaultcontext.xml" + }); + } + System.out.println("DONE."); + } + + /** + * The SeleniumManager is used for creating and closing Selenium instances. + * The abstract Context base class sets up this instance before the Context + * is used for creating selenium instances the first time. + */ + protected SeleniumManager seleniumManager_; + + private List<CodepointClient> codepointClients_ = new LinkedList<CodepointClient>();; + + private Map<String,String> config_ = new HashMap<String,String>(); + + private SetupType setupType_; + + protected void initContext() { + SetupType[] setupTypes = SetupType.values(); + for (int i = 0; i < setupTypes.length; i++) { + SetupType setupType = setupTypes[i]; + if (supportsSetupType(setupType)) { + if (contexts_.containsKey(setupType)) { + throw new IllegalArgumentException("There is already a Context defined for SetupType "+setupType.name()); + } + contexts_.put(setupType, this); + } + } + setConfigProperty("browserId", "*chrome"); + } + + protected abstract boolean supportsSetupType(SetupType setupType); + + private static Context getContext(SetupType setupType) { + Context c = contexts_.get(setupType); + if (c==null) { + throw new IllegalStateException("No Context found for SetupType "+setupType.name()); + } + return c; + } + + public SetupType getSetupType() { + return setupType_; + } + + public boolean isSingleVMSetupType() { + return getSetupType().isSingleVm(); + } + + public void setConfig(Map<String, String> config) { + Iterator<Map.Entry<String, String>> it = config.entrySet().iterator(); + while(it.hasNext()) { + Entry<String, String> entry = it.next(); + config_.put(entry.getKey(), entry.getValue()); + } + } + + public String getConfigProperty(String key) { + if (config_==null) { + throw new IllegalStateException("config_ must not be null."); + } + return config_.get(key); + } + + public void setConfigProperty(String key, String value) { + if (config_==null) { + throw new IllegalStateException("config_ must not be null."); + } + config_.put(key, value); + } + + public static Context setupContext(String testName, SetupType setupType) { + if (currentContext.get()!=null) { + throw new IllegalStateException("Context is already setup. You must do a context.tearDown() first before doing another Context.setupContext Mate!"); + } + Context c = getContext(setupType); + if (c==null) { + throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly?"); + } + currentContext.set(c); + System.out.println("============================"); + System.out.println("Context.setupContext START("+testName+","+setupType.name()+")"); + System.out.println("seleniumHost = "+c.getConfigProperty("seleniumHost")); + System.out.println("browserId = "+c.getConfigProperty("browserId")); + System.out.println("withCodepoints = "+c.getConfigProperty("withCodepoints")); + System.out.println("jmsBrokerUrl = "+c.getConfigProperty("jmsBrokerUrl")); + System.out.println("instanceId = "+c.getConfigProperty("instanceId")); + + if (setupType.isSingleVm()) { + // then we have exactly 1 url + System.out.println("singleVmOlatUrl = "+c.getConfigProperty("singleVmOlatUrl")); + } else { + // then we have multiple. unclear how many, so lets just loop + int nodeId = 1; + while(c.getConfigProperty("multiVmOlatUrl"+nodeId)!=null) { + System.out.println("multiVmOlatUrl"+nodeId+" = "+c.getConfigProperty("multiVmOlatUrl"+nodeId)); + nodeId++; + } + } + System.out.println("admin = "+c.getConfigProperty("adminUsername")+"/"+c.getConfigProperty("adminPassword")); + System.out.println("author = "+c.getConfigProperty("authorUsername")+"/"+c.getConfigProperty("authorPassword")); + System.out.println("student = "+c.getConfigProperty("studentUsername")+"/"+c.getConfigProperty("studentPassword")); + System.out.println("guest = "+c.getConfigProperty("guestUsername")+"/"+c.getConfigProperty("guestPassword")); + //............ + System.out.println("log4JConfigFilename = "+c.getConfigProperty(log4JConfigFilenameKey)); + + + c.seleniumManager_ = new SeleniumManager(testName); + c.setupType_ = setupType; + c.doSetupContext(setupType); + + System.out.println("Context.setupContext END("+testName+","+setupType.name()+")"); + System.out.println("============================"); + // and return the context itself + return c; + } + + public static Context getContext() { + Context c = currentContext.get(); + if (c==null) { + throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?"); + } + return c; + } + + /** + * Try to find out if it is a KnownIssueException somewhere in the olat.log - + * and if so, don't report it as the original failure but as a known issue so we immediately + * know from the test result that it is a known issue. + * <br/> + * Returns by default false, that is "Do not mask the test failure if ERROR encountered in olat.log". + * <br/> + * It never returns true, but it throws a AssertionFailedError if a "Known Issue" encountered. + * + * @param th + * @return + * @throws Exception + */ + public static boolean maskTestFailureOrError(Throwable th) throws Exception { + Context c = currentContext.get(); + if (c==null) { + throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?"); + } + if (c.doMaskTestFailureOrError(th)) { + return true; + } + if (th.getMessage().contains("INST-MSG-author")) { + throw new AssertionFailedError("Known Issue 3841 encountered."); + } + if (c.seleniumManager_.anySeleniumBrowserHasKnownIssue3857()) { + throw new AssertionFailedError("Known Issue 3857 encountered. (\"Please do not use the `Reload` or `Back` button of your browser.\" encountered in one of the browsers)"); + } + return false; + } + + protected boolean doMaskTestFailureOrError(Throwable th) throws Exception { + return false; + } + + public static void tearDown() { + System.out.println("======== TEARDOWNSTART ====="); + try{ + staticDoTearDown(); + } catch(Error er) { + er.printStackTrace(System.out); + throw er; + } catch(RuntimeException re) { + re.printStackTrace(System.out); + throw re; + } finally { + System.out.println("======= TEARDOWNFINALLY ===="); + } + } + + private final static void staticDoTearDown() { + Context c = currentContext.get(); + if (c==null) { + throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?"); + } + System.out.println("============================"); + System.out.println("Context.tearDown() START"); + + c.doTearDown(); + + System.out.println("----------------------------"); + System.out.println("Closing CodepointClients...."); + int cnt = 0; + for (Iterator<CodepointClient> it = c.codepointClients_.iterator(); it.hasNext();) { + System.out.println("CodepointClient["+cnt+"] START"); + CodepointClient codepointClient = it.next(); + try{ + System.out.println("CodepointClient["+cnt+"] fetching all codepoints for debug..."); + List<CodepointRef> codepoints = codepointClient.listAllCodepoints(); + System.out.println("CodepointClient["+cnt+"] going through all codepoints now..."); + for (Iterator<CodepointRef> it2 = codepoints.iterator(); it2.hasNext();) { + CodepointRef codepointRef = it2.next(); + System.out.println("[Codepoint-"+codepointClient+"]: "+codepointRef.getId()+", hitCount="+codepointRef.getHitCount()); + } + System.out.println("CodepointClient["+cnt+"] done with going through all codepoints."); + } catch(AssertionError ae) { + // ok, be silent here + } catch(Exception e) { + System.out.println("Exception in list codepoint: "+e); + e.printStackTrace(System.out); + } + System.out.println("CodepointClient["+cnt+"] closing codepointclient now..."); + codepointClient.close(); + System.out.println("CodepointClient["+cnt+"] END"); + cnt++; + } + System.out.println("Closed CodepointClients."); + System.out.println("----------------------------"); + + currentContext.set(null); + + System.out.println("Context.tearDown() END"); + System.out.println("============================"); + } + + protected abstract void doSetupContext(SetupType setupType); + + protected abstract void doTearDown(); + + /** + public void deleteAllLearningResourcesFromMyAuthors() { + WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardAdminOlatLoginInfos(1).getUsername()); + WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardAuthorOlatLoginInfos(1).getUsername()); + WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardStudentOlatLoginInfos(1).getUsername()); + WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardGuestOlatLoginInfos(1).getUsername()); + }**/ + + public Selenium createSelenium() { + return createSelenium(getStandardAdminOlatLoginInfos(1)); + } + + public Selenium createSelenium(int nodeId) { + return createSelenium(getStandardAdminOlatLoginInfos(nodeId)); + } + + public Selenium createSelenium(OlatLoginInfos loginInfos) { + Selenium selenium = seleniumManager_.createSelenium(loginInfos); + return selenium; + } + + public Selenium createSeleniumAndLogin() { + return createSeleniumAndLogin(getStandardAdminOlatLoginInfos(1)); + } + + public Selenium createSeleniumAndLogin(OlatLoginInfos loginInfos) { + Selenium selenium = seleniumManager_.createSelenium(loginInfos); + + OlatLoginHelper.olatLogin(selenium, loginInfos); + + // make sure the login worked + if (!"OLAT - Home".equals(selenium.getTitle())) { + throw new AssertionError("createSeleniumAndLogin failed - expected to be logged in now and seeing 'OLAT - Home' - but instead I'm on this page: "+selenium.getTitle()); + } + return selenium; + } + + /** + * Creates selenium, login and return an OLAT abstraction instance. + * @param loginInfos + * @return THE OLAT ABSTRACTION entry point + */ + public OLATWorkflowHelper getOLATWorkflowHelper(OlatLoginInfos loginInfos) { + Selenium selenium = seleniumManager_.createSelenium(loginInfos); + + OlatLoginHelper.olatLogin(selenium, loginInfos); + + // make sure the login worked + if (!"OLAT - Home".equals(selenium.getTitle())) { + throw new AssertionError("createSeleniumAndLogin failed - expected to be logged in now and seeing 'OLAT - Home' - but instead I'm on this page: "+selenium.getTitle()); + } + return new OLATWorkflowHelper(selenium); + } + + /** + * Create user + * @param nodeId + * @param username + * @param password + * @param isSystemUser + * @param userManagementRole + * @param groupManagementRole + * @param authorRole + * @param systemAdminRole + * @return + */ + public OlatLoginInfos createuserIfNotExists(int nodeId, + String username, String password, + boolean isSystemUser, + boolean userManagementRole, boolean groupManagementRole, boolean authorRole, boolean systemAdminRole) { + + try { + return WorkflowHelper.createUserIfNotExists(getStandardAdminOlatLoginInfos(nodeId), + username, password, + isSystemUser, + userManagementRole, groupManagementRole, authorRole, systemAdminRole); + } catch (InterruptedException e) { + e.printStackTrace(System.out); + throw new RuntimeException(e); + } + } + + /** + * Create user by login as admin with the given name and the standard password. + * @param nodeId + * @param username + * @param isSystemUser + * @param userManagementRole + * @param groupManagementRole + * @param authorRole + * @param systemAdminRole + * @return + */ + public OlatLoginInfos createuserIfNotExists( + int nodeId, + String username, + boolean isSystemUser, + boolean userManagementRole, boolean groupManagementRole, boolean authorRole, boolean systemAdminRole) { + return createuserIfNotExists(nodeId, username, getStandardPassword(), isSystemUser, userManagementRole, groupManagementRole, authorRole, systemAdminRole); + } + + public CodepointClient createCodepointClient(int nodeId) { + CodepointClient codepointClient; + try { + codepointClient = doCreateCodepointClient(nodeId); + } catch (Exception e) { + e.printStackTrace(System.out); + throw new RuntimeException(e); + } + codepointClients_.add(codepointClient); + return codepointClient; + } + + /** + * Creates a codepoint client for the server node with the given id. + * + * @param nodeId + * @return + * @throws Exception + */ + protected abstract CodepointClient doCreateCodepointClient(int nodeId) throws Exception; + + public OlatLoginInfos getStandardAdminOlatLoginInfos() { + if (!isSingleVMSetupType()) { + throw new IllegalStateException("In Cluster mode you need to specify the nodeId of this login"); + } + return getStandardAdminOlatLoginInfos(1); + } + + public OlatLoginInfos getStandardAuthorOlatLoginInfos() { + if (!isSingleVMSetupType()) { + throw new IllegalStateException("In Cluster mode you need to specify the nodeId of this login"); + } + return getStandardAuthorOlatLoginInfos(1); + } + + public OlatLoginInfos getStandardStudentOlatLoginInfos() { + return getStandardStudentOlatLoginInfos(1); + } + + public OlatLoginInfos getStandardGuestOlatLoginInfos() { + return getStandardGuestOlatLoginInfos(1); + } + + public OlatLoginInfos getStandardAdminOlatLoginInfos(int nodeId) { + return createLoginInfos(nodeId, getConfigProperty("adminUsername"), getConfigProperty("adminPassword")); + } + + public OlatLoginInfos getStandardAuthorOlatLoginInfos(int nodeId) { + return createLoginInfos(nodeId, getConfigProperty("authorUsername"), getConfigProperty("authorPassword")); + } + + public OlatLoginInfos getStandardStudentOlatLoginInfos(int nodeId) { + return createLoginInfos(nodeId, getConfigProperty("studentUsername"), getConfigProperty("studentPassword")); + } + + public OlatLoginInfos getStandardGuestOlatLoginInfos(int nodeId) { + return createLoginInfos(nodeId, getConfigProperty("guestUsername"), getConfigProperty("guestPassword")); + } + + protected String getOlatUrl(int nodeId) { + if (isSingleVMSetupType()) { + if (nodeId!=1) { + throw new IllegalArgumentException("Cannot refer to nodeId other than 1 while having SetupType set to SINGLE VM"); + } + return getConfigProperty("singleVmOlatUrl"); + } else { + return getConfigProperty("multiVmOlatUrl"+nodeId); + } + } + + protected OlatLoginInfos createLoginInfos(int nodeId, String username, String password) { + String olatUrl = getOlatUrl(nodeId); + try{ + return new OlatLoginInfos( + getConfigProperty("seleniumHost"), + getConfigProperty("browserId"), + olatUrl, + username, + password); + } catch(MalformedURLException e) { + throw new RuntimeException("MalformedURLException ("+olatUrl+") when creating admin login infos: "+e); + } + } + + /** + * Beware: this does not check if the user data is valid!!! + * @param nodeId + * @param username + * @param password + * @return Returns an OlatLoginInfos for the username, password, and nodeId. + */ + public OlatLoginInfos getOlatLoginInfo(int nodeId, String username, String password) { + //TODO:LD: see is user data check needed (e.g. admin login and check if username exists and change password to the given one) + return createLoginInfos(nodeId, username, password); + } + + /** + * Creates a OlatLoginInfos object using the context info and the standard password. + * @param nodeId + * @param username + * @return + */ + public OlatLoginInfos getOlatLoginInfo(int nodeId, String username) { + //TODO:LD: see is user data check needed (e.g. admin login and check if username exists and change password to the given one) + return createLoginInfos(nodeId, username, getStandardStudentOlatLoginInfos(1).getPassword()); + } + + /** + * Convention: all test users could use a standard password, and we assume that this is the default student password. + * @return + */ + private String getStandardPassword() { + return getStandardStudentOlatLoginInfos(1).getPassword(); + } + + /** + * Copies the localFile to the seleniumHost location. + * + * @param localFile + * @return + */ + public abstract String provideFileRemotely(File localFile); + + /** + * Restarts Selenium RC server. + * + * @throws AssertionError + */ + protected abstract void restartSeleniumServer() throws AssertionError; + + + +} diff --git a/src/test/java/org/olat/test/util/setup/context/SeleniumLocallyContext.java b/src/test/java/org/olat/test/util/setup/context/SeleniumLocallyContext.java new file mode 100644 index 0000000000000000000000000000000000000000..fbddf51e23b67f5a5f3951e1e84c7df39ced7a77 --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/context/SeleniumLocallyContext.java @@ -0,0 +1,97 @@ +package org.olat.test.util.setup.context; + +import java.io.File; + +import org.olat.test.util.setup.SetupType; +import org.olat.testutils.codepoints.client.CodepointClient; +import org.olat.testutils.codepoints.client.CodepointClientFactory; +import org.olat.testutils.codepoints.client.CommunicationException; + +/** + * Context for running selenium tests in eclipse. <br/> + * + * + * @author eglis + * + */ +public class SeleniumLocallyContext extends Context { + + public SeleniumLocallyContext() { + initContext(); + } + + @Override + protected boolean supportsSetupType(SetupType setupType) { + return true; + } + + @Override + protected void doSetupContext(SetupType setupType) { + System.out.println("Test run assumes SetupType: "+setupType.name()); + + String withCodepoints = getConfigProperty("withCodepoints"); + if("true".equals(withCodepoints)) { + assertCodepointServerReady(1); + } + } + + @Override + protected void doTearDown() { + System.out.println("Closing seleniums..."); + seleniumManager_.closeSeleniums(); + System.out.println("Done closing seleniums."); + } + + @Override + public CodepointClient doCreateCodepointClient(int nodeId) throws Exception { + return CodepointClientFactory.createCodepointClient(getConfigProperty("jmsBrokerUrl"), getConfigProperty("instanceId")+"-"+nodeId); + } + + @Override + public String provideFileRemotely(File localFile) { + if (!localFile.exists()) { + throw new AssertionError("File not found: "+localFile); + } + return localFile.getAbsolutePath(); + } + + protected void assertCodepointServerReady(int nodeId) { + try{ + final long start = System.currentTimeMillis(); + String jmsBrokerUrl = getConfigProperty("jmsBrokerUrl"); + String[] ids = CodepointClientFactory.listCodepointServerNodeIds(jmsBrokerUrl); + for (int i = 0; i < ids.length; i++) { + System.out.println("[SeleniumLocallyContext] DISCOVERED NODE_ID: "+ids[i]); + } + System.out.println("[SeleniumLocallyContext] Discovery took "+(System.currentTimeMillis()-start)/1000+"s"); + } catch(Exception e) { + System.out.println("[SeleniumLocallyContext] Exception while doing listCodepointServerNodeIds: "+e); + e.printStackTrace(System.out); + } + System.out.println("[SeleniumLocallyContext] asserting that the CodepointServer with nodeId="+nodeId+" is ready..."); + CodepointClient codepointClient = createCodepointClient(nodeId); + try { + codepointClient.listAllCodepoints(); + } catch (CommunicationException e) { + e.printStackTrace(System.out); + throw new AssertionError("Got a CommunicationException while making sure the CodepointServer was running in nodeId="+nodeId+" (exception="+e+")"); + } + codepointClient.close(); + System.out.println("[SeleniumLocallyContext] asserting that the CodepointServer with nodeId="+nodeId+" succeeded!"); + } + + /*@BeforeClass*/ + public void restartSeleniumServer() throws AssertionError { + //nothing to implement - the selenium RC server is started manually when running tests using this context + /*try { + SeleniumServer server = new SeleniumServer(); + server.stop(); + server.start(); + Thread.sleep(15000); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }*/ + } + +} diff --git a/src/test/java/org/olat/test/util/setup/context/SeleniumSuite.java b/src/test/java/org/olat/test/util/setup/context/SeleniumSuite.java new file mode 100644 index 0000000000000000000000000000000000000000..59f6ce11d4a03c2d00e2b15ffb63fe5fa2743d03 --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/context/SeleniumSuite.java @@ -0,0 +1,55 @@ +package org.olat.test.util.setup.context; + +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.runner.Runner; +import org.junit.runners.Suite; +import org.junit.runners.model.InitializationError; +import org.junit.runners.model.RunnerBuilder; +import org.olat.test.util.setup.SetupType; + +public class SeleniumSuite extends Suite { + + protected SeleniumSuite(Class<?> klass, Class<?>[] suiteClasses) + throws InitializationError { + super(klass, suiteClasses); + } + + + public SeleniumSuite(Class<?> klass, List<Runner> runners) + throws InitializationError { + super(klass, runners); + } + + public SeleniumSuite(Class<?> klass, RunnerBuilder builder) + throws InitializationError { + super(klass, builder); + } + + public SeleniumSuite(RunnerBuilder builder, Class<?> klass, + Class<?>[] suiteClasses) throws InitializationError { + super(builder, klass, suiteClasses); + } + + public SeleniumSuite(RunnerBuilder builder, Class<?>[] classes) + throws InitializationError { + super(builder, classes); + } + + + private static Context context; + + public void startSeleniumserver() throws Exception { + //context.restartSeleniumServer(); + } + + public void stopSeleniumServer() throws Exception { + //todo: implement this!!! + } + + @BeforeClass + public static void setupOnce() { + context = Context.setupContext(SeleniumSuite.class.getName(), SetupType.TWO_NODE_CLUSTER); + } +} diff --git a/src/test/java/org/olat/test/util/setup/steps/RuntimeExecHelper.java b/src/test/java/org/olat/test/util/setup/steps/RuntimeExecHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..b95b39755096d4034eff2281c9323155d5050517 --- /dev/null +++ b/src/test/java/org/olat/test/util/setup/steps/RuntimeExecHelper.java @@ -0,0 +1,201 @@ +package org.olat.test.util.setup.steps; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.concurrent.TimeoutException; + +public class RuntimeExecHelper { + + private static final long DEFAULT_MAX_TIMEOUT_IN_MILLIS = 10*60*1000; // 10 min + + static class ReaderRunnable implements Runnable { + + private final BufferedReader reader_; + private final String prefix_; + private final Thread thread_; + private transient boolean stop_ = false; + + public ReaderRunnable(String prefix, InputStream in) { + if (prefix==null) { + throw new IllegalArgumentException("prefix must not be null"); + } + if (in==null) { + throw new IllegalArgumentException("in must not be null"); + } + reader_ = new BufferedReader(new InputStreamReader(in)); + prefix_ = prefix; + thread_ = new Thread(this); + thread_.setDaemon(true); + thread_.start(); + } + + public void run() { + try { + while(true) { + synchronized(this) { + if (stop_) { + return; + } + } + String line = reader_.readLine(); + if (line==null) { + return; + } + System.out.println(prefix_+line); + } + } catch (IOException e) { + e.printStackTrace(); + return; + } finally { + if (reader_!=null) { + try { + reader_.close(); + } catch (IOException e) { + // silence in the library + } + } + } + } + + public void close() { + synchronized(this) { + stop_ = true; + } + if (reader_!=null) { + try { + reader_.close(); + } catch (IOException e) { + // silence in the library + } + } + } + + } + + static class WaitForWithTimeout implements Runnable { + + private final Process p_; + private Thread thread_ = null; + private boolean success_ = false; + private int result_; + + public WaitForWithTimeout(Process p) { + if (p==null) { + throw new IllegalArgumentException("p must not be null"); + } + p_ = p; + } + + public int waitFor(long timeout) throws TimeoutException { + if (thread_!=null) { + throw new IllegalStateException("already called waitFor"); + } + thread_ = new Thread(this); + thread_.setDaemon(true); + thread_.start(); + final long end = System.currentTimeMillis() + timeout; + synchronized(this) { + while(!success_) { + long diff = end - System.currentTimeMillis(); + if (diff<=0) { + break; + } else { + try { + wait(diff); + } catch (InterruptedException e) { + // ignore + } + } + } + if (success_) { + return result_; + } else { + thread_.interrupt(); + throw new TimeoutException(); + } + } + } + + public void run() { + try { + int result = p_.waitFor(); + synchronized(this) { + result_ = result; + success_ = true; + notifyAll(); + } + } catch (InterruptedException e) { + // ignore + } + } + + } + + public static String execWithStdOut(String cmd) throws Exception { + System.out.println("Executing the following command: "+cmd); + Process process = Runtime.getRuntime().exec(cmd); + + ReaderRunnable outReader = new ReaderRunnable("[STDOUT:] ", process.getInputStream()); + ReaderRunnable errReader = new ReaderRunnable("[STDERR:] ", process.getErrorStream()); + try{ + int errorCode = new WaitForWithTimeout(process).waitFor(DEFAULT_MAX_TIMEOUT_IN_MILLIS); + + BufferedReader stdOutReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + StringBuffer sb = new StringBuffer(); + while(true) { + String stdOutLine = stdOutReader.readLine(); + if (stdOutLine==null) { + break; + } + if (sb.length()!=0) { + sb.append(System.getProperty("line.separator")); + } + sb.append(stdOutLine); + System.out.println("[STDOUT:] "+stdOutLine); + } + BufferedReader stdErrReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + while(true) { + String stdErrLine = stdErrReader.readLine(); + if (stdErrLine==null) { + break; + } + System.out.println("[STDERR:] "+stdErrLine); + } + + if (errorCode!=0) { + System.out.println("Exec of '"+cmd+"' returned errorcode: "+errorCode); + throw new AssertionError("cmd failed. errorcode="+errorCode+", cmd="+cmd); + } else { + return sb.toString(); + } + } finally { + outReader.close(); + errReader.close(); + System.out.println("Done with execution of command: "+cmd); + } + } + + public static void exec(String cmd, boolean failOnError) throws Exception { + int errorCode = exec(cmd); + System.out.println("Exec of '"+cmd+"' returned errorcode: "+errorCode); + if (errorCode!=0 && failOnError) { + throw new AssertionError("cmd failed. errorcode="+errorCode+", cmd="+cmd); + } + } + + public static int exec(String cmd) throws Exception { + System.out.println("Executing the following command: "+cmd); + Process process = Runtime.getRuntime().exec(cmd); + ReaderRunnable outReader = new ReaderRunnable("[STDOUT:] ", process.getInputStream()); + ReaderRunnable errReader = new ReaderRunnable("[STDERR:] ", process.getErrorStream()); + try{ + return new WaitForWithTimeout(process).waitFor(DEFAULT_MAX_TIMEOUT_IN_MILLIS); + } finally { + outReader.close(); + errReader.close(); + System.out.println("Done with execution of command: "+cmd); + } + } +} diff --git a/src/test/java/org/olat/test/util/testng/JUnitXMLReporter.java b/src/test/java/org/olat/test/util/testng/JUnitXMLReporter.java new file mode 100644 index 0000000000000000000000000000000000000000..c0a9c48d91ee683ac5a4b17fead417992a72e534 --- /dev/null +++ b/src/test/java/org/olat/test/util/testng/JUnitXMLReporter.java @@ -0,0 +1,391 @@ +package org.olat.test.util.testng; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Pattern; + +import org.testng.ITestContext; +import org.testng.ITestResult; +import org.testng.TestListenerAdapter; +import org.testng.annotations.Test; + +/** + * Listener generating XML output suitable to be processed by JUnitReport. Copied from TestNG (www.testng.org) and + * modified + * @author Bela Ban + * @version $Id: JUnitXMLReporter.java,v 1.6 2008-08-12 08:22:59 eglis Exp $ + */ +public class JUnitXMLReporter extends TestListenerAdapter { + private String output_dir=null; + private String suffix=null; + + private static final String SUFFIX="test.suffix"; + private static final String XML_DEF="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"; + private static final String CDATA="![CDATA["; + private static final String LT="<"; + private static final String GT=">"; + private static final String SYSTEM_OUT="system-out"; + private static final String SYSTEM_ERR="system-err"; + + PrintStream old_stdout=System.out; + PrintStream old_stderr=System.err; + + + private final ConcurrentMap<Class, List<ITestResult>> classes=new ConcurrentHashMap<Class,List<ITestResult>>(); + + /** Map to keep systemout and systemerr associated with a class */ + final ConcurrentMap<Class,Tuple<ByteArrayOutputStream,ByteArrayOutputStream>> outputs=new ConcurrentHashMap<Class,Tuple<ByteArrayOutputStream,ByteArrayOutputStream>>(); + + ByteArrayOutputStream unsolicitedOut = new ByteArrayOutputStream(); + ByteArrayOutputStream unsolicitedErr = new ByteArrayOutputStream(); + + public static InheritableThreadLocal<Class> local=new InheritableThreadLocal<Class>(); + + + public JUnitXMLReporter() { + System.out.println("Start"); + } + + + public void onTestStart(ITestResult result) { + Class real_class=result.getTestClass().getRealClass(); + local.set(real_class); + print(old_stdout, "REAL CLASS: ", real_class.getName(), ""); + + List<ITestResult> results=classes.get(real_class); + if(results == null) { + results=new LinkedList<ITestResult>(); + classes.putIfAbsent(real_class, results); + } + + outputs.putIfAbsent(real_class, new Tuple<ByteArrayOutputStream,ByteArrayOutputStream>(new ByteArrayOutputStream(), new ByteArrayOutputStream())); + // old_stdout.println(Thread.currentThread() + " running " + real_class.getName() + "." + result.getName() + "()"); + } + + + + /** Invoked each time a test succeeds */ + public void onTestSuccess(ITestResult tr) { + Class real_class=tr.getTestClass().getRealClass(); + flushOtherOutput(real_class); + addTest(real_class, tr); + print(old_stdout, "OK: ", real_class.getName(), tr.getName()); + } + + public void onTestFailedButWithinSuccessPercentage(ITestResult tr) { + Class real_class=tr.getTestClass().getRealClass(); + flushOtherOutput(real_class); + addTest(tr.getTestClass().getRealClass(), tr); + print(old_stdout, "OK: ", real_class.getName(), tr.getName()); + } + + + + /** + * Invoked each time a test fails. + */ + public void onTestFailure(ITestResult tr) { + Class real_class=tr.getTestClass().getRealClass(); + flushOtherOutput(real_class); + addTest(tr.getTestClass().getRealClass(), tr); + print(old_stderr, "FAIL: ", real_class.getName(), tr.getName()); + } + + private void flushOtherOutput(Class real_class) { + if (unsolicitedOut.size()>0 || unsolicitedErr.size()>0) { + outputs.putIfAbsent(real_class, new Tuple<ByteArrayOutputStream,ByteArrayOutputStream>(unsolicitedOut, unsolicitedErr)); + unsolicitedOut = new ByteArrayOutputStream(); + unsolicitedErr = new ByteArrayOutputStream(); + } + } + + + /** + * Invoked each time a test is skipped. + */ + public void onTestSkipped(ITestResult tr) { + Class real_class=tr.getTestClass().getRealClass(); + flushOtherOutput(real_class); + addTest(tr.getTestClass().getRealClass(), tr); + print(old_stdout, "SKIP: ", real_class.getName(), tr.getName()); + } + + private static void print(PrintStream out, String msg, String classname, String method_name) { + out.println(msg + "[" + Thread.currentThread().getId() + "] " + classname + "." + method_name + "()"); + // out.println(msg + classname + "." + method_name + "()"); + } + + private void addTest(Class clazz, ITestResult result) { + List<ITestResult> results=classes.get(clazz); + if(results == null) { + results=new LinkedList<ITestResult>(); + classes.putIfAbsent(clazz, results); + } + + results=classes.get(clazz); + results.add(result); + } + + /** + * Invoked after the test class is instantiated and before any configuration method is called. + */ + public void onStart(ITestContext context) { + System.out.println("Changing System.out..."); + while (System.out instanceof SysOutPrintStream) { + System.setOut(((SysOutPrintStream)System.out).getOriginalSysOut()); + } + while (System.err instanceof SysOutPrintStream) { + System.setErr(((SysOutPrintStream)System.err).getOriginalSysOut()); + } + old_stdout=System.out; + old_stderr=System.err; + unsolicitedOut = new ByteArrayOutputStream(); + unsolicitedErr = new ByteArrayOutputStream(); + suffix=System.getProperty(SUFFIX); + if(suffix != null) + suffix=suffix.trim(); + output_dir=context.getOutputDirectory(); // + File.separator + context.getName() + suffix + ".xml"; + + System.setOut(new SysOutPrintStream(new JUnitXMLReporterOutputStream(this, 1), old_stdout)); + + System.setErr(new SysOutPrintStream(new JUnitXMLReporterOutputStream(this, 2), old_stderr)); + } + + /** + * Invoked after all the tests have run and all their + * Configuration methods have been called. + */ + public void onFinish(ITestContext context) { + System.out.println("Changing System.out back..."); + System.setOut(old_stdout); + System.setErr(old_stderr); + while (System.out instanceof SysOutPrintStream) { + System.setOut(((SysOutPrintStream)System.out).getOriginalSysOut()); + } + while (System.err instanceof SysOutPrintStream) { + System.setErr(((SysOutPrintStream)System.err).getOriginalSysOut()); + } + + try { + generateReport(); + } + catch(IOException e) { + e.printStackTrace(); + } + } + + /** + * generate the XML report given what we know from all the test results + */ + protected void generateReport() throws IOException { + for(Map.Entry<Class,List<ITestResult>> entry: classes.entrySet()) { + Class clazz=entry.getKey(); + List<ITestResult> results=entry.getValue(); + + int num_failures=getFailures(results); + int num_skips=getSkips(results); + int num_errors=getErrors(results); + long total_time=getTotalTime(results); + + String file_name=output_dir + File.separator + "TEST-" + clazz.getName(); + if(suffix != null) + file_name=file_name + "-" + suffix; + file_name=file_name + ".xml"; + FileWriter out=new FileWriter(file_name, false); // don't append, overwrite + try { + out.write(XML_DEF + "\n"); + + out.write("\n<testsuite " + + " failures=\"" + num_failures + + "\" errors=\"" + num_errors + + "\" skips=\"" + num_skips + + "\" name=\"" + clazz.getName()); + if(suffix != null) + out.write(" (" + suffix + ")"); + out.write("\" tests=\"" + results.size() + "\" time=\"" + (total_time / 1000.0) + "\">"); + + out.write("\n<properties>"); + Properties props=System.getProperties(); + + for(Map.Entry<Object,Object> tmp: props.entrySet()) { + out.write("\n <property name=\"" + tmp.getKey() + "\"" + + " value=\"" + tmp.getValue() + "\"/>"); + } + out.write("\n</properties>\n"); + + + for(ITestResult result: results) { + if(result == null) + continue; + long time=result.getEndMillis() - result.getStartMillis(); + out.write("\n <testcase classname=\"" + clazz.getName()); + if(suffix != null) + out.write(" (" + suffix + ")"); + out.write("\" name=\"" + result.getMethod().getMethodName() + + "\" time=\"" + (time/1000.0) + "\">"); + + Throwable ex=result.getThrowable(); + + switch(result.getStatus()) { + case ITestResult.SUCCESS: + case ITestResult.SUCCESS_PERCENTAGE_FAILURE: + break; + case ITestResult.FAILURE: + writeFailure("failure", result.getMethod().getMethod(), ex, "exception", out); + break; + case ITestResult.SKIP: + writeFailure("error", result.getMethod().getMethod(), ex, "SKIPPED", out); + break; + default: + writeFailure("error", result.getMethod().getMethod(), ex, "exception", out); + } + + out.write("\n</testcase>"); + } + + Tuple<ByteArrayOutputStream, ByteArrayOutputStream> stdout=outputs.get(clazz); + if(stdout != null) { + ByteArrayOutputStream system_out=stdout.getVal1(); + ByteArrayOutputStream system_err=stdout.getVal2(); + writeOutput(out, system_out.toString(), 1); + out.write("\n"); + writeOutput(out, system_err.toString(), 2); + } + + out.write("\n</testsuite>\n"); + } + finally { + out.close(); + } + } + + } + + private static String encode(String s) { + if (s==null) { + return null; + } + s = s.replaceAll(Pattern.quote("<"), "<"); + s = s.replaceAll(Pattern.quote(">"), ">"); + s = s.replaceAll(Pattern.quote("&"), "&"); + s = s.replaceAll(Pattern.quote("\""), """); + s = s.replaceAll(Pattern.quote("'"), "'"); + return s; + } + + private static void writeOutput(FileWriter out, String s, int type) throws IOException { + if(s != null && s.length() > 0) { + out.write("\n<" + (type == 2? SYSTEM_ERR : SYSTEM_OUT) + "><" + CDATA + "\n"); + out.write(encode(s)); + out.write("\n]]>"); + out.write("\n</" + (type == 2? SYSTEM_ERR : SYSTEM_OUT) + ">"); + } + } + + + private static void writeFailure(String type, Method method, Throwable ex, String msg, FileWriter out) throws IOException { + Test annotation=method.getAnnotation(Test.class); + if(annotation != null && ex != null) { + Class[] expected_exceptions=annotation.expectedExceptions(); + for(int i=0; i < expected_exceptions.length; i++) { + Class expected_exception=expected_exceptions[i]; + if(expected_exception.equals(ex.getClass())) { + return; + } + } + } + + out.write("\n<" + type + " type=\""); + if(ex != null) { + out.write(ex.getClass().getName() + "\" message=\"" + escape(ex.getMessage()) + "\">"); + printException(ex, out); + } + else + out.write("exception\" message=\"" + msg + "\">"); + out.write("\n</" + type + ">"); + } + + private static void printException(Throwable ex, FileWriter out) throws IOException { + if(ex == null) return; + StackTraceElement[] stack_trace=ex.getStackTrace(); + out.write("\n<" + CDATA + "\n"); + out.write(ex.getClass().getName() + " \n"); + for(int i=0; i < stack_trace.length; i++) { + StackTraceElement frame=stack_trace[i]; + try { + out.write("at " + frame.toString() + " \n"); + } + catch(IOException e) { + } + } + out.write("\n]]>"); + } + + private static String escape(String message) { + return encode(message); +// return message != null? message.replaceAll("<", LT).replaceAll(">", GT) : message; + } + + private static long getTotalTime(List<ITestResult> results) { + long start=0, stop=0; + for(ITestResult result: results) { + if(result == null) continue; + long tmp_start=result.getStartMillis(), tmp_stop=result.getEndMillis(); + if(start == 0) + start=tmp_start; + else { + start=Math.min(start, tmp_start); + } + + if(stop == 0) + stop=tmp_stop; + else { + stop=Math.max(stop, tmp_stop); + } + } + return stop-start; + } + + private static int getFailures(List<ITestResult> results) { + int retval=0; + for(ITestResult result: results) { + if(result != null && result.getStatus() == ITestResult.FAILURE) + retval++; + } + return retval; + } + + private static int getErrors(List<ITestResult> results) { + int retval=0; + for(ITestResult result: results) { + if(result != null + && result.getStatus() != ITestResult.SUCCESS + && result.getStatus() != ITestResult.SUCCESS_PERCENTAGE_FAILURE + && result.getStatus() != ITestResult.FAILURE) + retval++; + } + return retval; + } + + private static int getSkips(List<ITestResult> results) { + int retval=0; + for(ITestResult result: results) { + if(result != null && result.getStatus() == ITestResult.SKIP) + retval++; + } + return retval; + } + + + +} diff --git a/src/test/java/org/olat/test/util/testng/JUnitXMLReporterOutputStream.java b/src/test/java/org/olat/test/util/testng/JUnitXMLReporterOutputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..296e7ff3c3e6384ebcea4c1a307f0c1b1742ed58 --- /dev/null +++ b/src/test/java/org/olat/test/util/testng/JUnitXMLReporterOutputStream.java @@ -0,0 +1,47 @@ +package org.olat.test.util.testng; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + + +public class JUnitXMLReporterOutputStream extends OutputStream { + + private final JUnitXMLReporter reporter_; + + final int type_; // 1 == stdout, 2 == stderr + + public JUnitXMLReporterOutputStream(JUnitXMLReporter reporter, int type) { + reporter_ = reporter; + type_ = type; + if(type != 1 && type != 2) + throw new IllegalArgumentException("index has to be 1 or 2"); + } + + @Override + public void write(int b) throws IOException { + try{ + Class clazz=JUnitXMLReporter.local.get(); + if(clazz != null) { + Tuple<ByteArrayOutputStream,ByteArrayOutputStream> tuple=reporter_.outputs.get(clazz); + if(tuple != null) { + ByteArrayOutputStream sb=type_ == 1? tuple.getVal1() : tuple.getVal2(); + sb.write(b); + return; + } + } + if (type_==1) { + reporter_.unsolicitedOut.write(b); + } else { + reporter_.unsolicitedErr.write(b); + } + } finally { + if (type_==1) { + reporter_.old_stdout.write(b); + } else { + reporter_.old_stderr.write(b); + } + } + } + +} diff --git a/src/test/java/org/olat/test/util/testng/SysOutPrintStream.java b/src/test/java/org/olat/test/util/testng/SysOutPrintStream.java new file mode 100644 index 0000000000000000000000000000000000000000..c4dfd2da10ab647ba49e3b6d9e022916543e41bb --- /dev/null +++ b/src/test/java/org/olat/test/util/testng/SysOutPrintStream.java @@ -0,0 +1,23 @@ +package org.olat.test.util.testng; + +import java.io.OutputStream; +import java.io.PrintStream; + +public class SysOutPrintStream extends PrintStream { + + private final PrintStream originalSysout_; + + public SysOutPrintStream(OutputStream out, PrintStream originalSysout) { + super(out); + originalSysout_ = originalSysout; + } + + protected PrintStream getOriginalSysOut() { + return originalSysout_; + } + + @Override + public String toString() { + return "a SysOutPrintStream[origSysOut="+originalSysout_+"]"; + } +} diff --git a/src/test/java/org/olat/test/util/testng/Tuple.java b/src/test/java/org/olat/test/util/testng/Tuple.java new file mode 100644 index 0000000000000000000000000000000000000000..7c20be5750c24ee3bdb3d48a31b36056192fbcc0 --- /dev/null +++ b/src/test/java/org/olat/test/util/testng/Tuple.java @@ -0,0 +1,37 @@ +package org.olat.test.util.testng; + +/** + * Holds 2 values, useful when we have a map with a key, but more than 1 value and we don't want to create a separate + * holder object for the values, and don't want to pass the values as a list or array. + * @author Bela Ban + * @version $Id: Tuple.java,v 1.1 2008-07-22 14:50:18 eglis Exp $ + */ +public class Tuple<V1,V2> { + private V1 val1; + private V2 val2; + + public Tuple(V1 val1, V2 val2) { + this.val1=val1; + this.val2=val2; + } + + public V1 getVal1() { + return val1; + } + + public void setVal1(V1 val1) { + this.val1=val1; + } + + public V2 getVal2() { + return val2; + } + + public void setVal2(V2 val2) { + this.val2=val2; + } + + public String toString() { + return val1 + " : " + val2; + } +} diff --git a/src/test/profile/cluster/activemq/activemq.xml b/src/test/profile/cluster/activemq/activemq.xml new file mode 100644 index 0000000000000000000000000000000000000000..712d6b45e97d2d3749eb3beec7744df46c71a940 --- /dev/null +++ b/src/test/profile/cluster/activemq/activemq.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:amq="http://activemq.apache.org/schema/core" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://activemq.apache.org/schema/core + http://activemq.apache.org/schema/core/activemq-core.xsd + "> + <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="./target/activemq/data"> + <!-- The transport connectors ActiveMQ will listen to --> + <transportConnectors> + <transportConnector name="openwire" uri="tcp://0.0.0.0:${test.env.jms.broker.port}"/> + </transportConnectors> + </broker> +</beans> diff --git a/src/test/profile/cluster/tomcat-one/conf/server.xml b/src/test/profile/cluster/tomcat-one/conf/server.xml new file mode 100644 index 0000000000000000000000000000000000000000..8f6362967af953341c285989d328ae149938454a --- /dev/null +++ b/src/test/profile/cluster/tomcat-one/conf/server.xml @@ -0,0 +1,151 @@ +<?xml version='1.0' encoding='utf-8'?> + +<!-- MVN CONFIGURED FOR ${container.tomcat.one.port} --> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- Note: A "Server" is not itself a "Container", so you may not + define subcomponents such as "Valves" at this level. + Documentation at /docs/config/server.html + --> +<Server port="${container.tomcat.one.port.part}05" shutdown="SHUTDOWN"> + + <!--APR library loader. Documentation at /docs/apr.html --> + <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> + <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> + <Listener className="org.apache.catalina.core.JasperListener" /> + <!-- Prevent memory leaks due to use of particular java/javax APIs--> + <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> + <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --> + <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" /> + <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> + + <!-- Global JNDI resources + Documentation at /docs/jndi-resources-howto.html + --> + <GlobalNamingResources> + <!-- Editable user database that can also be used by + UserDatabaseRealm to authenticate users + --> + <Resource name="UserDatabase" auth="Container" + type="org.apache.catalina.UserDatabase" + description="User database that can be updated and saved" + factory="org.apache.catalina.users.MemoryUserDatabaseFactory" + pathname="conf/tomcat-users.xml" /> + </GlobalNamingResources> + + <!-- A "Service" is a collection of one or more "Connectors" that share + a single "Container" Note: A "Service" is not itself a "Container", + so you may not define subcomponents such as "Valves" at this level. + Documentation at /docs/config/service.html + --> + <Service name="Catalina"> + + <!--The connectors can use a shared executor, you can define one or more named thread pools--> + <!-- + <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" + maxThreads="150" minSpareThreads="4"/> + --> + + + <!-- A "Connector" represents an endpoint by which requests are received + and responses are returned. Documentation at : + Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) + Java AJP Connector: /docs/config/ajp.html + APR (HTTP/AJP) Connector: /docs/apr.html + Define a non-SSL HTTP/1.1 Connector on port 8181 + --> + <Connector port="${container.tomcat.one.port}" protocol="HTTP/1.1" + connectionTimeout="20000" + redirectPort="8443" /> + <!-- A "Connector" using the shared thread pool--> + <!-- + <Connector executor="tomcatThreadPool" + port="8181" protocol="HTTP/1.1" + connectionTimeout="20000" + redirectPort="8443" /> + --> + <!-- Define a SSL HTTP/1.1 Connector on port 8443 + This connector uses the JSSE configuration, when using APR, the + connector should be using the OpenSSL style configuration + described in the APR documentation --> + <!-- + <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" + maxThreads="150" scheme="https" secure="true" + clientAuth="false" sslProtocol="TLS" /> + --> + + <!-- Define an AJP 1.3 Connector on port 8109 --> + <Connector port="${container.tomcat.one.port.part}09" protocol="AJP/1.3" redirectPort="8443" /> + + + <!-- An Engine represents the entry point (within Catalina) that processes + every request. The Engine implementation for Tomcat stand alone + analyzes the HTTP headers included with the request, and passes them + on to the appropriate Host (virtual host). + Documentation at /docs/config/engine.html --> + + <!-- You should set jvmRoute to support load-balancing via AJP ie : + <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> + --> + <Engine name="Catalina" defaultHost="localhost"> + + <!--For clustering, please take a look at documentation at: + /docs/cluster-howto.html (simple how to) + /docs/config/cluster.html (reference documentation) --> + <!-- + <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> + --> + + <!-- The request dumper valve dumps useful debugging information about + the request and response data received and sent by Tomcat. + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.valves.RequestDumperValve"/> + --> + + <!-- This Realm uses the UserDatabase configured in the global JNDI + resources under the key "UserDatabase". Any edits + that are performed against this UserDatabase are immediately + available for use by the Realm. --> + <Realm className="org.apache.catalina.realm.UserDatabaseRealm" + resourceName="UserDatabase"/> + + <!-- Define the default virtual host + Note: XML Schema validation will not work with Xerces 2.2. + --> + <Host name="localhost" appBase="webapps" + unpackWARs="true" autoDeploy="true" + xmlValidation="false" xmlNamespaceAware="false"> + + <!-- SingleSignOn valve, share authentication between web applications + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> + --> + + <!-- Access log processes all example. + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" + prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/> + --> + + </Host> + </Engine> + </Service> +</Server> diff --git a/src/test/profile/cluster/tomcat-one/lib/olat.local.properties b/src/test/profile/cluster/tomcat-one/lib/olat.local.properties new file mode 100644 index 0000000000000000000000000000000000000000..fe35d39006e1f6000353a12dc3d874843d23e80d --- /dev/null +++ b/src/test/profile/cluster/tomcat-one/lib/olat.local.properties @@ -0,0 +1,76 @@ +######################### +# +# This olat.local.properties file is only used when running junit tests! (Unit tests run in its own classpath environment) +# Use this file to set properties that affect or are a prerequisite for your tests. +# +######################### +userdata.dir=${basedir}/target/olatdata +archive.dir=${userdata.dir}/deleted_archive +log.dir=${userdata.dir}/logs +folder.root=${userdata.dir}/bcroot + + +defaultlang=de +db.show_sql=false + +instance.id=${test.env.instance.id} + +generate.index.at.startup=false + +# for UserTest +keepUserEmailAfterDeletion=true +keepUserLoginAfterDeletion=true + +######################################################################## +# Clustering settings +######################################################################## + +# set to Cluster to enable, otherwise use SingleVM to disable cluster features +cluster.mode=Cluster +# each node requires a unique ID (1-64) starting at "1" +node.id=1 +server.port=${container.tomcat.one.port} +# certain servies (e.g., notifications, course logger etc. are not +# cluster capable and can only run on a single node - set this to +# enabled on that node +cluster.singleton.services = disabled +search.service=disabled +jmx.rmi.port=${test.env.jmx.rmi.port.1} +# JMS broker url's where the path (localhost:61700) - defines teh local adress and local port : +# SingleVM jms.broker.url +# jms.broker.url=vm://embedded?broker.persistent=false +# search.broker.url=vm://embedded?broker.persistent=false +# codepoint.jms.broker.url=vm://embedded?broker.persistent=false +# Cluster (remote) jms.broker.url +jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +search.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +codepoint.jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) + + +# enable/disable codepoint/breakpoint framework +codepoint_server.enabled=true +smtp.host=testing + +#hibernate.caching.singlevm.class=net.sf.ehcache.hibernate.EhCacheProvider +hibernate.caching.singlevm.class= +#org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory +#hibernate.caching.cluster.class=org.hibernate.cache.NoCacheProvider +hibernate.caching.cluster.class= +hibernate.caching.use.query.cache=false +hibernate.use.second.level.cache=false + +# +# if you like to run your tests against mysql just uncomment the following. Please do not commit it! +# + +db.vendor=mysql +# +# +db.name=${test.env.db.name} +db.user=${test.env.db.user} +db.pass=${test.env.db.pass} +db.host.port=${test.env.db.host.port} +# +db.database.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +# +db.hibernate.ddl.auto= diff --git a/src/test/profile/cluster/tomcat-one/lib/treecache.xml b/src/test/profile/cluster/tomcat-one/lib/treecache.xml new file mode 100644 index 0000000000000000000000000000000000000000..1078a6bd2cf6d0f2cef22c1fb09703d47653979c --- /dev/null +++ b/src/test/profile/cluster/tomcat-one/lib/treecache.xml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.0"> + + + <!-- + isolation levels supported: READ_COMMITTED and REPEATABLE_READ + nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated) + --> + <locking + isolationLevel="READ_COMMITTED" + lockParentForChildInsertRemove="false" + lockAcquisitionTimeout="20000" + nodeLockingScheme="mvcc" + writeSkewCheck="false" + concurrencyLevel="500"/> + + <!-- + Used to register a transaction manager and participate in ongoing transactions. + + <transaction + transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup" + syncRollbackPhase="false" + syncCommitPhase="false"/> + --> + + <!-- + Used to register JMX statistics in any available MBean server + --> + <jmxStatistics + enabled="true"/> + + <!-- + If region based marshalling is used, defines whether new regions are inactive on startup. + --> + <startup + regionsInactiveOnStartup="true"/> + + <!-- + Used to register JVM shutdown hooks. + hookBehavior: DEFAULT, REGISTER, DONT_REGISTER + --> + <shutdown + hookBehavior="DEFAULT"/> + + <!-- + Used to define async listener notification thread pool size + --> + <listeners + asyncPoolSize="1" + asyncQueueSize="1000000"/> + + <!-- + Used to enable invocation batching and allow the use of Cache.startBatch()/endBatch() methods. + --> + <invocationBatching + enabled="false"/> + + <!-- + serialization related configuration, used for replication and cache loading + --> +<!-- <serialization + objectInputStreamPoolSize="12" + objectOutputStreamPoolSize="14" + version="3.0.0" + marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller" + useLazyDeserialization="false" + useRegionBasedMarshalling="false"/> +--> + + <!-- + This element specifies that the cache is clustered. + modes supported: replication (r) or invalidation (i). + --> + <clustering mode="replication" clusterName="JBossCache-cluster"> + + <!-- + Defines whether to retrieve state on startup + --> + <stateRetrieval timeout="20000" fetchInMemoryState="false"/> + + <!-- + Network calls are synchronous. + --> + <sync replTimeout="20000"/> + <!-- + Uncomment this for async replication. + --> + <!--<async useReplQueue="true" replQueueInterval="10000" replQueueMaxElements="500" serializationExecutorPoolSize="20" serializationExecutorQueueSize="5000000"/>--> + + <!-- Uncomment to use Buddy Replication --> + <!-- + <buddy enabled="true" poolName="myBuddyPoolReplicationGroup" communicationTimeout="2000"> + <dataGravitation auto="true" removeOnFind="true" searchBackupTrees="true"/> + <locator class="org.jboss.cache.buddyreplication.NextMemberBuddyLocator"> + <properties> + numBuddies = 1 + ignoreColocatedBuddies = true + </properties> + </locator> + </buddy> + --> + + <!-- + Configures the JGroups channel. Looks up a JGroups config file on the classpath or filesystem. udp.xml + ships with jgroups.jar and will be picked up by the class loader. + --> + <jgroupsConfig> + + <UDP discard_incompatible_packets="true" enable_bundling="false" enable_diagnostics="false" ip_ttl="2" + loopback="false" max_bundle_size="64000" max_bundle_timeout="30" mcast_addr="224.0.0.0" + mcast_port="45566" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000" + oob_thread_pool.enabled="true" oob_thread_pool.keep_alive_time="10000" oob_thread_pool.max_threads="4" + oob_thread_pool.min_threads="1" oob_thread_pool.queue_enabled="true" oob_thread_pool.queue_max_size="10" + oob_thread_pool.rejection_policy="Run" thread_naming_pattern="pl" thread_pool.enabled="true" + thread_pool.keep_alive_time="30000" thread_pool.max_threads="25" thread_pool.min_threads="1" + thread_pool.queue_enabled="true" thread_pool.queue_max_size="10" thread_pool.rejection_policy="Run" + tos="8" ucast_recv_buf_size="20000000" ucast_send_buf_size="640000" use_concurrent_stack="true" + use_incoming_packet_handler="true"/> + <PING num_initial_members="3" timeout="2000"/> + <MERGE2 max_interval="30000" min_interval="10000"/> + <FD_SOCK/> + <FD max_tries="5" shun="true" timeout="10000"/> + <VERIFY_SUSPECT timeout="1500"/> + <pbcast.NAKACK discard_delivered_msgs="true" gc_lag="0" retransmit_timeout="300,600,1200,2400,4800" + use_mcast_xmit="false"/> + <UNICAST timeout="300,600,1200,2400,3600"/> + <pbcast.STABLE desired_avg_gossip="50000" max_bytes="400000" stability_delay="1000"/> + <pbcast.GMS join_timeout="5000" print_local_addr="true" shun="false" view_ack_collection_timeout="5000" + view_bundling="true"/> + <FRAG2 frag_size="60000"/> + <pbcast.STREAMING_STATE_TRANSFER/> + <pbcast.FLUSH timeout="0"/> + + </jgroupsConfig> + </clustering> + + <!-- + Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means + the eviction thread will never run. + --> + <eviction wakeUpInterval="500"> + <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm" eventQueueSize="200000"> + <property name="maxNodes" value="5000"/> + <property name="timeToLive" value="1000"/> + </default> + <!-- Example + <region name="/org/jboss/data1"> + <property name="timeToLive" value="2000"/> + </region> + --> + <!-- TIMESTAMP-CACHE FOR QUERY CACHE --> + <region name="/TS" algorithmClass="org.jboss.cache.eviction.NullEvictionAlgorithm" /> + </eviction> + + <!-- + Cache loaders. + + If passivation is enabled, state is offloaded to the cache loaders ONLY when evicted. Similarly, when the state + is accessed again, it is removed from the cache loader and loaded into memory. + + Otherwise, state is always maintained in the cache loader as well as in memory. + + Set 'shared' to true if all instances in the cluster use the same cache loader instance, e.g., are talking to the + same database. + --> + <loaders passivation="false" shared="false"> + <preload> + <node fqn="/org/jboss"/> + <node fqn="/org/tempdata"/> + </preload> + + <!-- + we can have multiple cache loaders, which get chained + --> + <loader class="org.jboss.cache.loader.JDBCCacheLoader" async="true" fetchPersistentState="true" + ignoreModifications="true" purgeOnStartup="true"> + + <properties> + cache.jdbc.table.name=jbosscache + cache.jdbc.table.create=true + cache.jdbc.table.drop=true + cache.jdbc.table.primarykey=jbosscache_pk + cache.jdbc.fqn.column=fqn + cache.jdbc.fqn.type=varchar(255) + cache.jdbc.node.column=node + cache.jdbc.node.type=blob + cache.jdbc.parent.column=parent + cache.jdbc.sql-concat=1 || 2 + cache.jdbc.driver = org.apache.derby.jdbc.EmbeddedDriver + cache.jdbc.url=jdbc:derby:jbossdbtomcatone;create=true + cache.jdbc.user=user1 + cache.jdbc.password=user1 + </properties> + <!-- alternatively use a connection from a datasorce, as per the code sample below--> + <!--<properties>--> + <!--cache.jdbc.datasource=AllSampleDS--> + <!--cache.jdbc.table.name=jbosscache--> + <!--cache.jdbc.table.create=true--> + <!--cache.jdbc.table.drop=true--> + <!--</properties>--> + <singletonStore enabled="true" class="org.jboss.cache.loader.SingletonStoreCacheLoader"> + <properties> + pushStateWhenCoordinator=true + pushStateWhenCoordinatorTimeout=20000 + </properties> + </singletonStore> + </loader> + </loaders> + + <!-- + Define custom interceptors. All custom interceptors need to extend org.jboss.cache.interceptors.base.CommandInterceptor + --> + <!-- + <customInterceptors> + <interceptor position="first" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"> + <property name="attrOne" value="value1" /> + <property name="attrTwo" value="value2" /> + </interceptor> + <interceptor position="last" class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/> + <interceptor index="3" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/> + <interceptor before="org.jboss.cache.interceptors.CallInterceptor" + class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/> + <interceptor after="org.jboss.cache.interceptors.CallInterceptor" + class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/> + </customInterceptors> + --> +</jbosscache> diff --git a/src/test/profile/cluster/tomcat-two/conf/server.xml b/src/test/profile/cluster/tomcat-two/conf/server.xml new file mode 100644 index 0000000000000000000000000000000000000000..3cfca529802ac8ee32546caa00ed4ac5027ae34a --- /dev/null +++ b/src/test/profile/cluster/tomcat-two/conf/server.xml @@ -0,0 +1,151 @@ +<?xml version='1.0' encoding='utf-8'?> + +<!-- MVN CONFIGURED FOR ${container.tomcat.two.port} --> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- Note: A "Server" is not itself a "Container", so you may not + define subcomponents such as "Valves" at this level. + Documentation at /docs/config/server.html + --> +<Server port="${container.tomcat.two.port.part}05" shutdown="SHUTDOWN"> + + <!--APR library loader. Documentation at /docs/apr.html --> + <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> + <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --> + <Listener className="org.apache.catalina.core.JasperListener" /> + <!-- Prevent memory leaks due to use of particular java/javax APIs--> + <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> + <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html --> + <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" /> + <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> + + <!-- Global JNDI resources + Documentation at /docs/jndi-resources-howto.html + --> + <GlobalNamingResources> + <!-- Editable user database that can also be used by + UserDatabaseRealm to authenticate users + --> + <Resource name="UserDatabase" auth="Container" + type="org.apache.catalina.UserDatabase" + description="User database that can be updated and saved" + factory="org.apache.catalina.users.MemoryUserDatabaseFactory" + pathname="conf/tomcat-users.xml" /> + </GlobalNamingResources> + + <!-- A "Service" is a collection of one or more "Connectors" that share + a single "Container" Note: A "Service" is not itself a "Container", + so you may not define subcomponents such as "Valves" at this level. + Documentation at /docs/config/service.html + --> + <Service name="Catalina"> + + <!--The connectors can use a shared executor, you can define one or more named thread pools--> + <!-- + <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" + maxThreads="150" minSpareThreads="4"/> + --> + + + <!-- A "Connector" represents an endpoint by which requests are received + and responses are returned. Documentation at : + Java HTTP Connector: /docs/config/http.html (blocking & non-blocking) + Java AJP Connector: /docs/config/ajp.html + APR (HTTP/AJP) Connector: /docs/apr.html + Define a non-SSL HTTP/1.1 Connector on port 8181 + --> + <Connector port="${container.tomcat.two.port}" protocol="HTTP/1.1" + connectionTimeout="20000" + redirectPort="8443" /> + <!-- A "Connector" using the shared thread pool--> + <!-- + <Connector executor="tomcatThreadPool" + port="8181" protocol="HTTP/1.1" + connectionTimeout="20000" + redirectPort="8443" /> + --> + <!-- Define a SSL HTTP/1.1 Connector on port 8443 + This connector uses the JSSE configuration, when using APR, the + connector should be using the OpenSSL style configuration + described in the APR documentation --> + <!-- + <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" + maxThreads="150" scheme="https" secure="true" + clientAuth="false" sslProtocol="TLS" /> + --> + + <!-- Define an AJP 1.3 Connector on port 8109 --> + <Connector port="${container.tomcat.two.port.part}09" protocol="AJP/1.3" redirectPort="8443" /> + + + <!-- An Engine represents the entry point (within Catalina) that processes + every request. The Engine implementation for Tomcat stand alone + analyzes the HTTP headers included with the request, and passes them + on to the appropriate Host (virtual host). + Documentation at /docs/config/engine.html --> + + <!-- You should set jvmRoute to support load-balancing via AJP ie : + <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1"> + --> + <Engine name="Catalina" defaultHost="localhost"> + + <!--For clustering, please take a look at documentation at: + /docs/cluster-howto.html (simple how to) + /docs/config/cluster.html (reference documentation) --> + <!-- + <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> + --> + + <!-- The request dumper valve dumps useful debugging information about + the request and response data received and sent by Tomcat. + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.valves.RequestDumperValve"/> + --> + + <!-- This Realm uses the UserDatabase configured in the global JNDI + resources under the key "UserDatabase". Any edits + that are performed against this UserDatabase are immediately + available for use by the Realm. --> + <Realm className="org.apache.catalina.realm.UserDatabaseRealm" + resourceName="UserDatabase"/> + + <!-- Define the default virtual host + Note: XML Schema validation will not work with Xerces 2.2. + --> + <Host name="localhost" appBase="webapps" + unpackWARs="true" autoDeploy="true" + xmlValidation="false" xmlNamespaceAware="false"> + + <!-- SingleSignOn valve, share authentication between web applications + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> + --> + + <!-- Access log processes all example. + Documentation at: /docs/config/valve.html --> + <!-- + <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" + prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/> + --> + + </Host> + </Engine> + </Service> +</Server> diff --git a/src/test/profile/cluster/tomcat-two/lib/olat.local.properties b/src/test/profile/cluster/tomcat-two/lib/olat.local.properties new file mode 100644 index 0000000000000000000000000000000000000000..7b6e9faf80f9d924e02099031917ca4dce4c4d43 --- /dev/null +++ b/src/test/profile/cluster/tomcat-two/lib/olat.local.properties @@ -0,0 +1,75 @@ +######################### +# +# This olat.local.properties file is only used when running junit tests! (Unit tests run in its own classpath environment) +# Use this file to set properties that affect or are a prerequisite for your tests. +# +######################### +userdata.dir=${basedir}/target/olatdata +archive.dir=${userdata.dir}/deleted_archive +log.dir=${userdata.dir}/logs +folder.root=${userdata.dir}/bcroot + +defaultlang=de +db.show_sql=false + +instance.id=${test.env.instance.id} + +generate.index.at.startup=false + +# for UserTest +keepUserEmailAfterDeletion=true +keepUserLoginAfterDeletion=true + +######################################################################## +# Clustering settings +######################################################################## + +# set to Cluster to enable, otherwise use SingleVM to disable cluster features +cluster.mode=Cluster +# each node requires a unique ID (1-64) starting at "1" +node.id=2 +server.port=${container.tomcat.two.port} +# certain servies (e.g., notifications, course logger etc. are not +# cluster capable and can only run on a single node - set this to +# enabled on that node +cluster.singleton.services = enabled +search.service=enabled +jmx.rmi.port=${test.env.jmx.rmi.port.2} +# JMS broker url's where the path (localhost:61700) - defines teh local adress and local port : +# SingleVM jms.broker.url +# jms.broker.url=vm://embedded?broker.persistent=false +# search.broker.url=vm://embedded?broker.persistent=false +# codepoint.jms.broker.url=vm://embedded?broker.persistent=false +# Cluster (remote) jms.broker.url +jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +search.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +codepoint.jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) + + +# enable/disable codepoint/breakpoint framework +codepoint_server.enabled=true +smtp.host=testing + +#hibernate.caching.singlevm.class=net.sf.ehcache.hibernate.EhCacheProvider +hibernate.caching.singlevm.class= +#org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory +#hibernate.caching.cluster.class=org.hibernate.cache.NoCacheProvider +hibernate.caching.cluster.class= +hibernate.use.second.level.cache=false +hibernate.caching.use.query.cache=false + +# +# if you like to run your tests against mysql just uncomment the following. Please do not commit it! +# + +db.vendor=mysql +# +# +db.name=${test.env.db.name} +db.user=${test.env.db.user} +db.pass=${test.env.db.pass} +db.host.port=${test.env.db.host.port} +# +db.database.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +# +db.hibernate.ddl.auto= diff --git a/src/test/profile/cluster/tomcat-two/lib/treecache.xml b/src/test/profile/cluster/tomcat-two/lib/treecache.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf62fae8811d72484372a9558e48ad4b7c7cd94d --- /dev/null +++ b/src/test/profile/cluster/tomcat-two/lib/treecache.xml @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.0"> + + + <!-- + isolation levels supported: READ_COMMITTED and REPEATABLE_READ + nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated) + --> + <locking + isolationLevel="READ_COMMITTED" + lockParentForChildInsertRemove="false" + lockAcquisitionTimeout="20000" + nodeLockingScheme="mvcc" + writeSkewCheck="false" + concurrencyLevel="500"/> + + <!-- + Used to register a transaction manager and participate in ongoing transactions. + + <transaction + transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup" + syncRollbackPhase="false" + syncCommitPhase="false"/> + --> + + <!-- + Used to register JMX statistics in any available MBean server + --> + <jmxStatistics + enabled="true"/> + + <!-- + If region based marshalling is used, defines whether new regions are inactive on startup. + --> + <startup + regionsInactiveOnStartup="true"/> + + <!-- + Used to register JVM shutdown hooks. + hookBehavior: DEFAULT, REGISTER, DONT_REGISTER + --> + <shutdown + hookBehavior="DEFAULT"/> + + <!-- + Used to define async listener notification thread pool size + --> + <listeners + asyncPoolSize="1" + asyncQueueSize="1000000"/> + + <!-- + Used to enable invocation batching and allow the use of Cache.startBatch()/endBatch() methods. + --> + <invocationBatching + enabled="false"/> + + <!-- + serialization related configuration, used for replication and cache loading + --> +<!-- <serialization + objectInputStreamPoolSize="12" + objectOutputStreamPoolSize="14" + version="3.0.0" + marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller" + useLazyDeserialization="false" + useRegionBasedMarshalling="false"/> +--> + + <!-- + This element specifies that the cache is clustered. + modes supported: replication (r) or invalidation (i). + --> + <clustering mode="replication" clusterName="JBossCache-cluster"> + + <!-- + Defines whether to retrieve state on startup + --> + <stateRetrieval timeout="20000" fetchInMemoryState="false"/> + + <!-- + Network calls are synchronous. + --> + <sync replTimeout="20000"/> + <!-- + Uncomment this for async replication. + --> + <!--<async useReplQueue="true" replQueueInterval="10000" replQueueMaxElements="500" serializationExecutorPoolSize="20" serializationExecutorQueueSize="5000000"/>--> + + <!-- Uncomment to use Buddy Replication --> + <!-- + <buddy enabled="true" poolName="myBuddyPoolReplicationGroup" communicationTimeout="2000"> + <dataGravitation auto="true" removeOnFind="true" searchBackupTrees="true"/> + <locator class="org.jboss.cache.buddyreplication.NextMemberBuddyLocator"> + <properties> + numBuddies = 1 + ignoreColocatedBuddies = true + </properties> + </locator> + </buddy> + --> + + <!-- + Configures the JGroups channel. Looks up a JGroups config file on the classpath or filesystem. udp.xml + ships with jgroups.jar and will be picked up by the class loader. + --> + <jgroupsConfig> + + <UDP discard_incompatible_packets="true" enable_bundling="false" enable_diagnostics="false" ip_ttl="2" + loopback="false" max_bundle_size="64000" max_bundle_timeout="30" mcast_addr="224.0.0.0" + mcast_port="45566" mcast_recv_buf_size="25000000" mcast_send_buf_size="640000" + oob_thread_pool.enabled="true" oob_thread_pool.keep_alive_time="10000" oob_thread_pool.max_threads="4" + oob_thread_pool.min_threads="1" oob_thread_pool.queue_enabled="true" oob_thread_pool.queue_max_size="10" + oob_thread_pool.rejection_policy="Run" thread_naming_pattern="pl" thread_pool.enabled="true" + thread_pool.keep_alive_time="30000" thread_pool.max_threads="25" thread_pool.min_threads="1" + thread_pool.queue_enabled="true" thread_pool.queue_max_size="10" thread_pool.rejection_policy="Run" + tos="8" ucast_recv_buf_size="20000000" ucast_send_buf_size="640000" use_concurrent_stack="true" + use_incoming_packet_handler="true"/> + <PING num_initial_members="3" timeout="2000"/> + <MERGE2 max_interval="30000" min_interval="10000"/> + <FD_SOCK/> + <FD max_tries="5" shun="true" timeout="10000"/> + <VERIFY_SUSPECT timeout="1500"/> + <pbcast.NAKACK discard_delivered_msgs="true" gc_lag="0" retransmit_timeout="300,600,1200,2400,4800" + use_mcast_xmit="false"/> + <UNICAST timeout="300,600,1200,2400,3600"/> + <pbcast.STABLE desired_avg_gossip="50000" max_bytes="400000" stability_delay="1000"/> + <pbcast.GMS join_timeout="5000" print_local_addr="true" shun="false" view_ack_collection_timeout="5000" + view_bundling="true"/> + <FRAG2 frag_size="60000"/> + <pbcast.STREAMING_STATE_TRANSFER/> + <pbcast.FLUSH timeout="0"/> + + </jgroupsConfig> + </clustering> + + <!-- + Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means + the eviction thread will never run. + --> + <eviction wakeUpInterval="500"> + <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm" eventQueueSize="200000"> + <property name="maxNodes" value="5000"/> + <property name="timeToLive" value="1000"/> + </default> + <!-- Example + <region name="/org/jboss/data1"> + <property name="timeToLive" value="2000"/> + </region> + --> + <!-- TIMESTAMP-CACHE FOR QUERY CACHE --> + <region name="/TS" algorithmClass="org.jboss.cache.eviction.NullEvictionAlgorithm" /> + </eviction> + + <!-- + Cache loaders. + + If passivation is enabled, state is offloaded to the cache loaders ONLY when evicted. Similarly, when the state + is accessed again, it is removed from the cache loader and loaded into memory. + + Otherwise, state is always maintained in the cache loader as well as in memory. + + Set 'shared' to true if all instances in the cluster use the same cache loader instance, e.g., are talking to the + same database. + --> + <loaders passivation="false" shared="false"> + <preload> + <node fqn="/org/jboss"/> + <node fqn="/org/tempdata"/> + </preload> + + <!-- + we can have multiple cache loaders, which get chained + --> + <loader class="org.jboss.cache.loader.JDBCCacheLoader" async="true" fetchPersistentState="true" + ignoreModifications="true" purgeOnStartup="true"> + + <properties> + cache.jdbc.table.name=jbosscache + cache.jdbc.table.create=true + cache.jdbc.table.drop=true + cache.jdbc.table.primarykey=jbosscache_pk + cache.jdbc.fqn.column=fqn + cache.jdbc.fqn.type=varchar(255) + cache.jdbc.node.column=node + cache.jdbc.node.type=blob + cache.jdbc.parent.column=parent + cache.jdbc.sql-concat=1 || 2 + cache.jdbc.driver = org.apache.derby.jdbc.EmbeddedDriver + cache.jdbc.url=jdbc:derby:jbossdbtomcattwo;create=true + cache.jdbc.user=user1 + cache.jdbc.password=user1 + </properties> + <!-- alternatively use a connection from a datasorce, as per the code sample below--> + <!--<properties>--> + <!--cache.jdbc.datasource=AllSampleDS--> + <!--cache.jdbc.table.name=jbosscache--> + <!--cache.jdbc.table.create=true--> + <!--cache.jdbc.table.drop=true--> + <!--</properties>--> + <singletonStore enabled="true" class="org.jboss.cache.loader.SingletonStoreCacheLoader"> + <properties> + pushStateWhenCoordinator=true + pushStateWhenCoordinatorTimeout=20000 + </properties> + </singletonStore> + </loader> + </loaders> + + <!-- + Define custom interceptors. All custom interceptors need to extend org.jboss.cache.interceptors.base.CommandInterceptor + --> + <!-- + <customInterceptors> + <interceptor position="first" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"> + <property name="attrOne" value="value1" /> + <property name="attrTwo" value="value2" /> + </interceptor> + <interceptor position="last" class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/> + <interceptor index="3" class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/> + <interceptor before="org.jboss.cache.interceptors.CallInterceptor" + class="org.jboss.cache.config.parsing.custominterceptors.BbbCustomInterceptor"/> + <interceptor after="org.jboss.cache.interceptors.CallInterceptor" + class="org.jboss.cache.config.parsing.custominterceptors.AaaCustomInterceptor"/> + </customInterceptors> + --> +</jbosscache> diff --git a/src/test/profile/hsql/olat.local.properties b/src/test/profile/hsql/olat.local.properties new file mode 100644 index 0000000000000000000000000000000000000000..03d791b01c6cacb3cc65f3c51e55b59ce0d4cc85 --- /dev/null +++ b/src/test/profile/hsql/olat.local.properties @@ -0,0 +1,43 @@ +######################### +# +# This olat.local.properties file is only used when running junit tests! (Unit tests run in its own classpath environment) +# Use this file to set properties that affect or are a prerequisite for your tests. +# from test/profile/hsql +######################### + +db.vendor=test +defaultlang=de +db.show_sql=false + +generate.index.at.startup=false + +# for UserTest +keepUserEmailAfterDeletion=true +keepUserLoginAfterDeletion=true + +# do not run upgrades and scheduled jobs and such +cluster.singleton.services = disabled + +# SingleVM jms.broker.url +jms.broker.url=vm://embedded?broker.persistent=false +search.broker.url=vm://embedded?broker.persistent=false +codepoint.jms.broker.url=vm://embedded?broker.persistent=false +# Cluster (remote) jms.broker.url +#jms.broker.url=failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0) +#search.broker.url=failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0) +#codepoint.jms.broker.url=failover:(tcp://localhost:61616?wireFormat.maxInactivityDuration=0) + + +# enable/disable codepoint/breakpoint framework +codepoint_server.enabled=true +# +# if you like to run your tests against mysql just uncomment the following. Please do not commit it! +# + +#db.vendor=mysql +# +# +#db.name=olattest +#db.user=olat +#db.pass=olat +db.hibernate.ddl.auto=create diff --git a/src/test/profile/mysql/olat.local.properties b/src/test/profile/mysql/olat.local.properties new file mode 100644 index 0000000000000000000000000000000000000000..2ac95e4acfaab92e314a65dbced0759d19497bb6 --- /dev/null +++ b/src/test/profile/mysql/olat.local.properties @@ -0,0 +1,52 @@ +######################### +# +# This olat.local.properties file is only used when running junit tests! (Unit tests run in its own classpath environment) +# Use this file to set properties that affect or are a prerequisite for your tests. +# +######################### + +defaultlang=de +db.show_sql=false + +instance.id=${test.env.instance.id} + +generate.index.at.startup=false + +# for UserTest +keepUserEmailAfterDeletion=true +keepUserLoginAfterDeletion=true + +# do not run upgrades and scheduled jobs and such +cluster.singleton.services = disabled +jmx.rmi.port=${test.env.jmx.rmi.port.0} + +# SingleVM jms.broker.url +jms.broker.url=vm://embedded?broker.persistent=false +search.broker.url=vm://embedded?broker.persistent=false +codepoint.jms.broker.url=vm://embedded?broker.persistent=false +# Cluster (remote) jms.broker.url +#jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +#search.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) +#codepoint.jms.broker.url=failover:(tcp://localhost:${test.env.jms.broker.port}?wireFormat.maxInactivityDuration=0) + + +# enable/disable codepoint/breakpoint framework +codepoint_server.enabled=true +smtp.host=testing + +# +# +# if you like to run your tests against mysql just uncomment the following. Please do not commit it! +# + +db.vendor=mysql +# +# +db.name=${test.env.db.name} +db.user=${test.env.db.user} +db.pass=${test.env.db.pass} +db.host.port=${test.env.db.host.port} +# +db.database.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +# +db.hibernate.ddl.auto=${test.env.db.hibernate.ddl.auto} diff --git a/src/test/profile/selenium/config/additionalUserContext.xml b/src/test/profile/selenium/config/additionalUserContext.xml new file mode 100644 index 0000000000000000000000000000000000000000..4cca58d560bda5d8ef4a27ab3bb0bdd2595088d5 --- /dev/null +++ b/src/test/profile/selenium/config/additionalUserContext.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + +<context:property-placeholder location="classpath:serviceconfig/olat.properties, classpath:olat.local.properties" /> + +<!-- EXAMPLE SPRING CONFIG FILE FOR ADDITIONAL TEST USERS --> +<!-- Copy this file to the top of your web-app CLASSPATH e.g. webapp/WEB-INF/classes and add your test-users to additionalTestUsers-list --> +<!-- Delete this two line which contains 'REMOVE THIS LINE TO ENABLE' below --> + + +<bean class="org.olat.user.TestUserAdder"> + <constructor-arg ref="userModule"></constructor-arg> + + <property name="additionalTestUsers"> + <list> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="author2" /> + <property name="firstName" value="Aurich2" /> + <property name="lastName" value="Thorw2" /> + <property name="email" value="author2@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="true" /> + <property name="admin" value="false" /> + + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="learner2" /> + <property name="firstName" value="Leisa2" /> + <property name="lastName" value="Arnerich2" /> + <property name="email" value="learner2@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="usermgr2" /> + <property name="firstName" value="Marc2" /> + <property name="lastName" value="Bond2" /> + <property name="email" value="usermgr2@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + <property name="userManager" value="true" /> + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="groupmgr2" /> + <property name="firstName" value="Alexandra2" /> + <property name="lastName" value="Jeunet2" /> + <property name="email" value="groupmgr2@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + <property name="groupManager" value="true" /> + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="test21" /> + <property name="firstName" value="Thomas21" /> + <property name="lastName" value="Est21" /> + <property name="email" value="test21@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="test22" /> + <property name="firstName" value="Till22" /> + <property name="lastName" value="Estobesto22" /> + <property name="email" value="test22@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + </bean> + <bean class="org.olat.user.DefaultUser"> + <!-- constructor arg is userName --> + <constructor-arg type="java.lang.String" value="test23" /> + <property name="firstName" value="Tanja23" /> + <property name="lastName" value="Estelle23" /> + <property name="email" value="test23@olat-newinstallation.org" /> + <property name="password" value="test2011" /> + <property name="language" value="${defaultlang}" /> + <property name="guest" value="false" /> + <property name="author" value="false" /> + <property name="admin" value="false" /> + </bean> + </list> + </property> +</bean> + + +</beans> diff --git a/src/test/profile/selenium/config/defaultcontext.xml b/src/test/profile/selenium/config/defaultcontext.xml new file mode 100644 index 0000000000000000000000000000000000000000..c31391736d49d267a918b3b02bb101db315d133a --- /dev/null +++ b/src/test/profile/selenium/config/defaultcontext.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" +> + + + <bean class="org.olat.test.util.setup.context.SeleniumLocallyContext" id="seleniumcontext"> + <property name="config"> + <map> + <entry key="seleniumHost" value="localhost"/> + + <!-- enable codepoints tests --> + <entry key="withCodepoints" value="true"/> + <entry key="instanceId" value="${test.env.instance.id}"/> + <entry key="jmsBrokerUrl" value="tcp://localhost:${test.env.jms.broker.port}"/> + + <!-- default test users (in the olat instance use the additionaUserContext.xml to add these users) --> + <entry key="adminUsername" value="administrator"/> + <entry key="adminPassword" value="olat"/> + <entry key="authorUsername" value="author2"/> + <entry key="authorPassword" value="test2011"/> + <entry key="studentUsername" value="learner2"/> + <entry key="studentPassword" value="test2011"/> + <entry key="guestUsername" value="guest"/> + <entry key="guestPassword" value="guest"/> + + <!-- olat tested instances--> + <entry key="multiVmOlatUrl1" value="http://localhost:${container.tomcat.one.port}/olat/dmz/"/> + <entry key="multiVmOlatUrl2" value="http://localhost:${container.tomcat.two.port}/olat/dmz/"/> + <entry key="singleVmOlatUrl" value="http://localhost:${container.tomcat.one.port}/olat/dmz/"/> + + <entry key="browserId" value="*firefox /Applications/FirefoxEnglish.app/Contents/MacOS/firefox-bin"/> + + <entry key="log4jConfigFilename" value="log4j.remote.properties"/> + </map> + </property> + </bean> + +</beans> diff --git a/src/test/profile/selenium/config/testng.xml b/src/test/profile/selenium/config/testng.xml new file mode 100644 index 0000000000000000000000000000000000000000..456d3edd69cca0eab20b1c3224a36c946ca0a6a2 --- /dev/null +++ b/src/test/profile/selenium/config/testng.xml @@ -0,0 +1,132 @@ +<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" > + +<suite name="SeleniumTesting72x" verbose="1" > + + <test name="fragilePackage" junit="true"> + <classes> + <class name="org.olat.test.functional.portfolio.CreateFillAndShareMapTest" /> + <class name="org.olat.test.functional.codepoints.cluster.CopyCourseTest" /> + <class name="org.olat.test.functional.course.run.EditInfoMessageTest" /> + <class name="org.olat.test.functional.course.run.UploadFilesInCourseTest" /> + </classes> + </test> + + <test name="loadPackage" junit="true"> + <classes> + <class name="org.olat.test.load.LoginLoadTest" /> + <class name="org.olat.test.load.MultiBrowserClusterEnrolmentLoadManualtest" /> + <class name="org.olat.test.load.OpenAllCoursesOnFirstPageTest" /> + <class name="org.olat.test.load.OpenAllCoursesTest" /> + </classes> + </test> + + <test name="Nopackage" junit="true"> + <classes> + <class name="org.olat.test.functional.courseeditor.courseEditor_concurrenciesEditTest" /> + <class name="org.olat.test.functional.courseeditor.CourseEditor_EditCoursePreviewRunTest" /> + <class name="org.olat.test.functional.courseeditor.CourseEditor_concurrencyEditAndExportTest" /> + <class name="org.olat.test.functional.courseeditor.CoursePublishInvalidateClusterTest" /> + <class name="org.olat.test.functional.courseeditor.CreateBlogTest" /> + <class name="org.olat.test.functional.courseeditor.courseEditor_insertElementsAMTest" /> + <class name="org.olat.test.functional.courseeditor.CreatePodcastTest" /> + <class name="org.olat.test.functional.courseeditor.CoursePublishInvalidateSingleVMTest" /> + <class name="org.olat.test.functional.courseeditor.OpenEditSessionTest" /> + <class name="org.olat.test.functional.courseeditor.CourseRenameTest" /> + <class name="org.olat.test.functional.courseeditor.MoveDeleteElementsTest" /> + <class name="org.olat.test.functional.courseeditor.DeletePublishIncompleteElementsTest" /> + <class name="org.olat.test.functional.courseeditor.EnrolmentCreateGroupsWithCSVTest" /> + <class name="org.olat.test.functional.courseeditor.courseEditor_consistencyPublishTest" /> + <class name="org.olat.test.functional.usermanagement.ImportUserTest" /> + <class name="org.olat.test.functional.usermanagement.UserSettingsTest" /> + <class name="org.olat.test.functional.usermanagement.UserRolesTest" /> + <class name="org.olat.test.functional.usermanagement.DeleteUserTest" /> + <class name="org.olat.test.functional.groups.GroupConcurrenciesTest" /> + <class name="org.olat.test.functional.groups.CreateProjectGroupAddUsersTest" /> + <class name="org.olat.test.functional.groups.CreateProjectGroupTest" /> + <class name="org.olat.test.functional.groups.CreateProjectGroupConfigureToolsTest" /> + <class name="org.olat.test.functional.lr.TestBlogAndPodcastLinks" /> + <class name="org.olat.test.functional.lr.lr_createCourseAMTest" /> + <class name="org.olat.test.functional.lr.lr_createCourseTest" /> + <class name="org.olat.test.functional.lr.lr_createTestTest" /> + <class name="org.olat.test.functional.lr.lr_createResourcefolderTest" /> + <class name="org.olat.test.functional.lr.lr_createQuestionnaireTest" /> + <class name="org.olat.test.functional.lr.lr_createGlossaryTest" /> + <class name="org.olat.test.functional.lr.DeleteAllCoursesTest" /> + <class name="org.olat.test.functional.lr.lr_createWikiTest" /> + <class name="org.olat.test.functional.lr.CPTest" /> + <class name="org.olat.test.functional.lr.ClusterWikiTest" /> + <class name="org.olat.test.functional.lr.lr_RemoveOwnerTest" /> + <class name="org.olat.test.functional.lr.lr_concurrenciesDelete" /> + <class name="org.olat.test.functional.home.FolderTest" /> + <class name="org.olat.test.functional.home.HomeSettingsTest" /> + <class name="org.olat.test.functional.administration.InfoMessageClusterTest" /> + <class name="org.olat.test.functional.administration.ASetupFNTestCase" /> + <class name="org.olat.test.functional.test.CombiQuestionnaireTest" /> + <class name="org.olat.test.functional.test.TestEditorCombiTest" /> + <class name="org.olat.test.functional.test.CheckTestAttempts" /> + <class name="org.olat.test.functional.codepoints.cluster.CourseEditingTest" /> + <class name="org.olat.test.functional.codepoints.cluster.NewLearningGroupTest" /> + <class name="org.olat.test.functional.codepoints.cluster.ConcurrentEnrolmentWithCheckpointsTest" /> + <class name="org.olat.test.functional.codepoints.cluster.ClusteredCourseExportTest" /> + <class name="org.olat.test.functional.codepoints.cluster.OpenNewFoTopicTest" /> + <class name="org.olat.test.functional.codepoints.cluster.Open2NewFoTopicsTest" /> + <class name="org.olat.test.functional.codepoints.cluster.AssessmentWithCodepointsTest" /> + <class name="org.olat.test.functional.portfolio.CollectOrCreateArtefactTest" /> + <class name="org.olat.test.functional.group.management.ConcurrentEnrolmentTest" /> + <class name="org.olat.test.functional.group.management.GroupManagementCombiTest" /> + <class name="org.olat.test.functional.group.management.EnrolmentWaitinglistTest" /> + <class name="org.olat.test.functional.group.management.ConcurrentVisibilityTest" /> + <class name="org.olat.test.functional.group.management.EnrollmentWithSizeLimitationTest" /> + <class name="org.olat.test.functional.course.CopyCourseTest2" /> + <class name="org.olat.test.functional.course.CourseCloseTest" /> + <class name="org.olat.test.functional.course.run.AccessVisibilityTest" /> + <class name="org.olat.test.functional.course.run.EditAndConfigurePodcastTest" /> + <class name="org.olat.test.functional.course.run.ConcurrentForumRepliesTest" /> + <class name="org.olat.test.functional.course.run.UseLTITest" /> + <class name="org.olat.test.functional.course.run.EditAndConfigureBlogTest" /> + <class name="org.olat.test.functional.course.run.AssessmentToolRemoveTutorTest" /> + <class name="org.olat.test.functional.course.run.ConcurrentEditCourseNodeTest" /> + <class name="org.olat.test.functional.course.run.CourseImportWithAllBBTest" /> + <class name="org.olat.test.functional.course.assessment.AssessmentFormTest" /> + <class name="org.olat.test.functional.course.assessment.BulkAssessmentTest" /> + <class name="org.olat.test.functional.course.assessment.AssessmentTest" /> + <class name="org.olat.test.functional.course.assessment.GroupDependentAssessmentTest" /> + <class name="org.olat.test.functional.course.assessment.AssessmentElementTest" /> + <class name="org.olat.test.functional.course.CourseWizardVisibiltyTest" /> + <class name="org.olat.test.functional.course.topic.TopicAssignmentSuite" /> + </classes> + </test> +</suite> + +<!-- TODO KI <class name="org.olat.test.functional.lr.CreateLearningRessourcesTest" /> --> +<!-- from suite CombiQuestionnaireTest <class name="org.olat.test.functional.test.CreateQuestionnaireWithAllQuestionTypes" /> --> +<!-- from suite TestEditorCombiTest <class name="org.olat.test.functional.test.CreateTstInEditor" /> --> +<!-- from suite TestEditorCombiTest <class name="org.olat.test.functional.test.TstRun" /> --> +<!-- from suite CombiQuestionnaireTest <class name="org.olat.test.functional.test.IntegrateQuestionnaireAndCheckAttempts" /> --> +<!-- from suite TestEditorCombiTest <class name="org.olat.test.functional.test.IntegrateTstInCourse" /> --> +<!-- from suite TestEditorCombiTest <class name="org.olat.test.functional.test.ChangeTstInEditor" /> --> +<!-- <class name="org.olat.test.functional.codepoints.cluster.MultiBrowserClusterNewLearningAreaTstDisabled3440" /> --> +<!-- <class name="org.olat.test.functional.codepoints.cluster.MultiBrowserClusterDeleteProjectGroupTstDISABLED3654" /> --> +<!-- <class name="org.olat.test.functional.codepoints.cluster.CourseGroupChatClusterTest" /> --> +<!-- from suite GroupManagementCombiTest <class name="org.olat.test.functional.group.management.ConfigureToolsLearningGroup" /> --> +<!-- from suite GroupManagementCombiTest <class name="org.olat.test.functional.group.management.EnrolmentLearningGroup" /> --> +<!-- from suite GroupManagementCombiTest <class name="org.olat.test.functional.group.management.CreateLearningGroupLearningArea" /> --> +<!-- <class name="org.olat.test.functional.group.management.MultiBrowserClusterUpdateLearningAreaTstDisabled3444" /> --> +<!-- <class name="org.olat.test.functional.group.management.CollaborationToolsTest" /> only one test which needs chat --> +<!-- <class name="org.olat.test.functional.course.chat.CourseGroupChatAndPollingTest" /> --> +<!-- <class name="org.olat.test.functional.course.chat.ChatTest" /> --> +<!-- from suite TopicAssignmentSuite <class name="org.olat.test.functional.course.topic.CreateAndConfigureTopicAssignmentTest" /> --> +<!-- from suite TopicAssignmentSuite <class name="org.olat.test.functional.course.topic.CreateTopicInTopicAssignmentTest" /> --> +<!-- from suite TopicAssignmentSuite <class name="org.olat.test.functional.course.topic.UploadInTopicsTest" /> --> +<!-- from suite TopicAssignmentSuite <class name="org.olat.test.functional.course.topic.SelectTopicsAndAcceptCandidatesTest" /> --> +<!-- <class name="org.olat.test.functional.search.MultiUserSearchTest" /> --> + + +<!-- + + find org/olat/test/functional/ -name "*.java" | awk 'BEGIN{FS=".";}{gsub(/\//,".");gsub(".java","");print "<class name=\"" $0 "\" />";}' + + <excludes> + <exclude>**/lr_concurrenciesDelete.java</exclude> + </excludes> +--> diff --git a/src/test/profile/selenium/firefoxprofile/.parentlock b/src/test/profile/selenium/firefoxprofile/.parentlock new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_001_ b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_001_ new file mode 100644 index 0000000000000000000000000000000000000000..08e7df176454f3ee5eeda13efa0adaa54828dfd8 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_001_ differ diff --git a/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_002_ b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_002_ new file mode 100644 index 0000000000000000000000000000000000000000..08e7df176454f3ee5eeda13efa0adaa54828dfd8 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_002_ differ diff --git a/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_003_ b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_003_ new file mode 100644 index 0000000000000000000000000000000000000000..08e7df176454f3ee5eeda13efa0adaa54828dfd8 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_003_ differ diff --git a/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_MAP_ b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_MAP_ new file mode 100644 index 0000000000000000000000000000000000000000..68543d98a3e4b60a927b0d7eb441a8906f27a528 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/Cache/_CACHE_MAP_ differ diff --git a/src/test/profile/selenium/firefoxprofile/XPC.mfasl b/src/test/profile/selenium/firefoxprofile/XPC.mfasl new file mode 100644 index 0000000000000000000000000000000000000000..c01c211393da8d0e90c2cf6356237bfde94634fe Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/XPC.mfasl differ diff --git a/src/test/profile/selenium/firefoxprofile/XUL.mfasl b/src/test/profile/selenium/firefoxprofile/XUL.mfasl new file mode 100644 index 0000000000000000000000000000000000000000..fc03f92cb530ac481a6ff9303ae06dfdecbeb0dd Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/XUL.mfasl differ diff --git a/src/test/profile/selenium/firefoxprofile/bookmarkbackups/bookmarks-2011-04-29.json b/src/test/profile/selenium/firefoxprofile/bookmarkbackups/bookmarks-2011-04-29.json new file mode 100644 index 0000000000000000000000000000000000000000..22d6a1801bafc4c5dcc45c4857e0ff84d5c23c02 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/bookmarkbackups/bookmarks-2011-04-29.json @@ -0,0 +1 @@ +{"title":"","id":1,"dateAdded":1304093457830074,"lastModified":1304093457830493,"type":"text/x-moz-place-container","root":"placesRoot","children":[{"title":"Bookmarks Menu","id":2,"parent":1,"dateAdded":1304093457830267,"lastModified":1304093458064020,"type":"text/x-moz-place-container","root":"bookmarksMenuFolder","children":[{"title":"Recently Bookmarked","id":7,"parent":2,"annos":[{"name":"Places/SmartBookmark","flags":0,"expires":4,"mimeType":null,"type":3,"value":"RecentlyBookmarked"}],"type":"text/x-moz-place","uri":"place:folder=BOOKMARKS_MENU&folder=UNFILED_BOOKMARKS&folder=TOOLBAR&sort=12&excludeQueries=1&excludeItemIfParentHasAnnotation=livemark%2FfeedURI&maxResults=10&queryType=1"},{"index":1,"title":"Recent Tags","id":8,"parent":2,"annos":[{"name":"Places/SmartBookmark","flags":0,"expires":4,"mimeType":null,"type":3,"value":"RecentTags"}],"type":"text/x-moz-place","uri":"place:sort=14&type=6&maxResults=10&queryType=1"},{"index":2,"title":"","id":9,"parent":2,"dateAdded":1304093457979095,"lastModified":1304093457979095,"type":"text/x-moz-place-separator"},{"index":3,"title":"Get Bookmark Add-ons","id":10,"parent":2,"dateAdded":1304093458053322,"lastModified":1304093458056185,"type":"text/x-moz-place","uri":"https://addons.mozilla.org/en-US/firefox/bookmarks/"},{"index":4,"title":"","id":13,"parent":2,"dateAdded":1304093458058082,"lastModified":1304093458058082,"type":"text/x-moz-place-separator"},{"index":5,"title":"Ubuntu and Free Software links","id":14,"parent":2,"dateAdded":1181129907000000,"lastModified":1180687506000000,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Information and resources about Ubuntu, Debian and Free Software in general"}],"type":"text/x-moz-place-container","children":[{"title":"Ubuntu","id":15,"parent":14,"dateAdded":1181129907000000,"lastModified":1181129907000000,"type":"text/x-moz-place","uri":"http://www.ubuntulinux.org/"},{"index":1,"title":"Ubuntu Wiki (community-edited website)","id":16,"parent":14,"dateAdded":1181129907000000,"lastModified":1181129907000000,"type":"text/x-moz-place","uri":"http://wiki.ubuntu.com/"},{"index":2,"title":"Make a Support Request to the Ubuntu Community","id":17,"parent":14,"dateAdded":1181129907000000,"lastModified":1181129907000000,"type":"text/x-moz-place","uri":"https://answers.launchpad.net/ubuntu/+addquestion"},{"index":3,"title":"Debian (Ubuntu is based on Debian)","id":18,"parent":14,"dateAdded":1181129907000000,"lastModified":1181129907000000,"type":"text/x-moz-place","uri":"http://www.debian.org/"},{"index":4,"title":"Ubuntu One - The personal cloud that brings your digital life together","id":19,"parent":14,"dateAdded":1304093458063232,"lastModified":1181129907000000,"type":"text/x-moz-place","uri":"https://one.ubuntu.com/"}]},{"index":6,"title":"Mozilla Firefox","id":20,"parent":2,"dateAdded":1304093458064020,"lastModified":1180687506000000,"type":"text/x-moz-place-container","children":[{"title":"Help and Tutorials","id":21,"parent":20,"dateAdded":1304093458064259,"lastModified":1304093458064952,"type":"text/x-moz-place","uri":"http://www.mozilla.com/en-US/firefox/help/"},{"index":1,"title":"Customize Firefox","id":22,"parent":20,"dateAdded":1304093458065128,"lastModified":1304093458065763,"type":"text/x-moz-place","uri":"http://www.mozilla.com/en-US/firefox/customize/"},{"index":2,"title":"Get Involved","id":23,"parent":20,"dateAdded":1304093458065939,"lastModified":1304093458066566,"type":"text/x-moz-place","uri":"http://www.mozilla.com/en-US/firefox/community/"},{"index":3,"title":"About Us","id":24,"parent":20,"dateAdded":1304093458066740,"lastModified":1304093458067366,"type":"text/x-moz-place","uri":"http://www.mozilla.com/en-US/firefox/about/"}]}]},{"index":1,"title":"Bookmarks Toolbar","id":3,"parent":1,"dateAdded":1304093457830345,"lastModified":1304093458057409,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar"}],"type":"text/x-moz-place-container","root":"toolbarFolder","children":[{"title":"Most Visited","id":6,"parent":3,"annos":[{"name":"Places/SmartBookmark","flags":0,"expires":4,"mimeType":null,"type":3,"value":"MostVisited"}],"type":"text/x-moz-place","uri":"place:sort=8&redirectsMode=2&maxResults=10"},{"index":1,"title":"Getting Started","id":11,"parent":3,"dateAdded":1304093458056989,"lastModified":1304093458057261,"type":"text/x-moz-place","uri":"http://www.mozilla.com/en-US/firefox/central/"},{"index":2,"title":"Latest Headlines","id":12,"parent":3,"dateAdded":1304093458057409,"lastModified":1304093467774535,"livemark":1,"annos":[{"name":"placesInternal/READ_ONLY","flags":0,"expires":4,"mimeType":null,"type":1,"value":1},{"name":"livemark/feedURI","flags":0,"expires":4,"mimeType":null,"type":3,"value":"http://fxfeeds.mozilla.com/en-US/firefox/headlines.xml"},{"name":"livemark/siteURI","flags":0,"expires":4,"mimeType":null,"type":3,"value":"http://fxfeeds.mozilla.com/en-US/firefox/livebookmarks/"},{"name":"livemark/expiration","flags":0,"expires":4,"mimeType":null,"type":2,"value":1304094067195},{"name":"livemark/loadfailed","flags":0,"expires":4,"mimeType":null,"type":1,"value":1}],"type":"text/x-moz-place-container","children":[]}]},{"index":2,"title":"Tags","id":4,"parent":1,"dateAdded":1304093457830419,"lastModified":1304093457830811,"type":"text/x-moz-place-container","root":"tagsFolder","children":[]},{"index":3,"title":"Unsorted Bookmarks","id":5,"parent":1,"dateAdded":1304093457830493,"lastModified":1304093457976994,"type":"text/x-moz-place-container","root":"unfiledBookmarksFolder","children":[]}]} \ No newline at end of file diff --git a/src/test/profile/selenium/firefoxprofile/cert8.db b/src/test/profile/selenium/firefoxprofile/cert8.db new file mode 100644 index 0000000000000000000000000000000000000000..ac40a3325724b598ba93a314d250bd03eb7f479f Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/cert8.db differ diff --git a/src/test/profile/selenium/firefoxprofile/compatibility.ini b/src/test/profile/selenium/firefoxprofile/compatibility.ini new file mode 100644 index 0000000000000000000000000000000000000000..2bc67ed2e869012a26f435edfd01322e8a636300 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/compatibility.ini @@ -0,0 +1,5 @@ +[Compatibility] +LastVersion=3.6.16_20110323142937/20110323142937 +LastOSABI=Linux_x86-gcc3 +LastPlatformDir=/usr/lib/firefox-3.6.16 +LastAppDir=/usr/lib/firefox-3.6.16 diff --git a/src/test/profile/selenium/firefoxprofile/compreg.dat b/src/test/profile/selenium/firefoxprofile/compreg.dat new file mode 100644 index 0000000000000000000000000000000000000000..81f477750a688f8da825d10a86efca45dad722e8 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/compreg.dat @@ -0,0 +1,1957 @@ +Generated File. Do not edit. + +[HEADER] +Version,0,5 + +[COMPONENTS] +rel:NetworkGeolocationProvider.js,1300895266000 +rel:nsUrlClassifierListManager.js,1300895266000 +rel:nsPlacesAutoComplete.js,1300895266000 +rel:nsHandlerService.js,1300895266000 +rel:libbrowsercomps.so,1300895506000 +rel:FeedProcessor.js,1300895266000 +rel:nsINIProcessor.js,1300895266000 +rel:nsBlocklistService.js,1300895266000 +rel:nsLoginInfo.js,1300895266000 +rel:nsWebHandlerApp.js,1300895266000 +rel:nsMicrosummaryService.js,1300895266000 +rel:nsSafebrowsingApplication.js,1300895266000 +rel:nsContentDispatchChooser.js,1300895266000 +rel:nsUrlClassifierLib.js,1300895266000 +rel:nsSearchService.js,1300895266000 +rel:txEXSLTRegExFunctions.js,1300895266000 +rel:nsBrowserContentHandler.js,1300895266000 +rel:pluginGlue.js,1300895266000 +rel:nsProxyAutoConfig.js,1300895266000 +rel:nsDefaultCLH.js,1300895266000 +rel:nsExtensionManager.js,1300895266000 +rel:GPSDGeolocationProvider.js,1300895266000 +rel:nsLoginManager.js,1300895266000 +rel:nsHelperAppDlg.js,1300895266000 +rel:nsBadCertHandler.js,1300895266000 +rel:nsPrivateBrowsingService.js,1300895266000 +rel:nsTaggingService.js,1300895266000 +rel:nsSidebar.js,1300895266000 +rel:libnkgnomevfs.so,1300895525000 +rel:nsAddonRepository.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-service.js,1273149890000 +rel:libmozgnome.so,1300895525000 +rel:libimgicon.so,1300895506000 +rel:nsPlacesTransactionsService.js,1300895266000 +rel:nsSetDefaultBrowser.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-http-observer.js,1273149890000 +rel:nsContentPrefService.js,1300895266000 +rel:libdbusservice.so,1300895506000 +rel:nsUpdateTimerManager.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-channel-listener.js,1273149890000 +rel:nsSessionStartup.js,1300895266000 +rel:nsFilePicker.js,1300895266000 +rel:nsTryToClose.js,1300895266000 +rel:nsSessionStore.js,1300895266000 +rel:nsLivemarkService.js,1300895266000 +rel:FeedConverter.js,1300895266000 +rel:nsSearchSuggestions.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/components/aboutHome.js,1288194175000 +rel:nsLoginManagerPrompter.js,1300895266000 +rel:libbrowserdirprovider.so,1300895506000 +rel:nsPlacesDBFlush.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-trace-service.js,1273149890000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/components/pluginGlue.js,1288194175000 +rel:nsURLFormatter.js,1300895266000 +rel:WebContentConverter.js,1300895266000 +rel:nsFormAutoComplete.js,1300895266000 +rel:storage-mozStorage.js,1300895266000 +rel:FeedWriter.js,1300895266000 +rel:nsBrowserGlue.js,1300895266000 +rel:storage-Legacy.js,1300895266000 +rel:nsDownloadManagerUI.js,1300895266000 +rel:fuelApplication.js,1300895266000 +abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-annotations.js,1273149890000 +rel:jsconsole-clhandler.js,1300895266000 + +[CLASSIDS] +{bfc310d2-38a0-11d3-8cd3-0060b0fc14a3},,application/x-mozilla-static,,nsLayoutModule +{a7f800e0-4306-11d4-98d0-001083010e9b},@mozilla.org/uriloader/external-helper-app-service;1,application/x-mozilla-static,Netscape External Helper App Service,docshell_provider +{a47ef526-6e48-4574-9d60-3164e271f75e},,application/x-mozilla-static,,nsLayoutModule +{75656ad9-bd13-4c5d-939a-ec6351eea0cc},,application/x-mozilla-static,,nsComposerModule +{ba6151ad-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6ec5f479-8e13-4403-b6ca-fe4c2dca14fd},,text/javascript,,rel:nsINIProcessor.js +{495eca42-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{0cd233e0-7a86-11d3-915c-006008a6edf6},,application/x-mozilla-static,,nsI18nModule +{73bb7c12-dbab-4ae2-aecf-a0331dec916f},,application/x-mozilla-static,,nsUCvMathModule +{cb6593e0-f9b2-11d2-bdd6-000064657374},@mozilla.org/js/xpc/XPConnect;1,application/x-mozilla-static,,xpconnect +{e768ebef-70f9-4fe3-8835-4f4f3fd996e2},,application/x-mozilla-static,,nsUCvMathModule +{229fa115-9412-4d32-baf3-2fc407f76fb1},,text/javascript,,rel:FeedConverter.js +{4bfaa9f0-1dd2-11b2-afae-a82cbaa0b606},,application/x-mozilla-static,,PKI +{f1299dc2-1dd1-11b2-a347-ee6b7660e048},,application/x-mozilla-static,,JavaScript_Debugger +{c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a},,text/javascript,,rel:nsPlacesDBFlush.js +{5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6},,application/x-mozilla-static,,nsToolkitCompsModule +{6394eeae-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{d4f2b600-b5c1-11d6-b483-cc97c63e567c},,application/x-mozilla-static,,nsLayoutModule +{748a1132-671a-409a-8d1d-f1cdf6b3a6b4},,application/x-mozilla-static,,nsI18nModule +{fcacef24-2b40-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{a496d0a2-dff7-4e23-bd65-1ca742fa178a},,application/x-mozilla-static,,NSS +{2d524fd3-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{8323fad0-2102-11d4-8142-000064657374},,application/x-mozilla-static,,nsParserModule +{16786594-0296-4471-8096-8f84497ca428},,application/x-mozilla-static,,NSS +{a5570462-1dd1-11b2-9d19-df30a27fbdc4},,application/x-mozilla-static,,nsFileViewModule +{c0773e90-5799-4eff-ad03-3ebcd85624ac},,application/x-mozilla-static,,RemoteServiceModule +{ba6151ba-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{f7fa4581-238e-11d5-a73c-ab64fb68f2bc},,application/x-mozilla-static,,embedcomponents +{8b1ae382-51a9-4972-b930-56977a57919d},,text/javascript,,rel:nsWebHandlerApp.js +{10f2f5f0-f103-4901-980f-ba11bd70d60d},,application/x-mozilla-static,,nsToolkitCompsModule +{9416bfb4-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{be9a53ae-c7e9-11d3-8cda-0060b0fc14a3},@mozilla.org/network/file-input-stream;1,application/x-mozilla-static,nsFileInputStream,necko +{a0f827e1-8ab6-11d5-a14b-005004832142},,application/x-mozilla-static,,nsUConvModule +{a6cf9124-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{d3f69889-e13a-4321-980c-a39332e21f34},,application/x-mozilla-static,,nsWidgetGtk2Module +{05bae29d-8aef-486d-84aa-53f48f146811},,application/x-mozilla-static,,xpconnect +{660d8ca8-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eebb-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{0c4f1ddc-1dd2-11b2-9d95-f2fdf113044b},,application/x-mozilla-static,,NSS +{7b8556ac-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{a15789aa-8903-462b-81e9-4aa2cff4d5cb},,application/x-mozilla-static,,NSS +{12663f3a-a311-4606-83eb-b6b9108dcc36},,text/javascript,,rel:pluginGlue.js +{bc0017e3-2438-47be-a567-41db58f17627},,application/x-mozilla-static,,docshell_provider +{ff41913b-546a-4bff-9201-dc9b2c032eba},@mozilla.org/network/url-parser;1?auth=maybe,application/x-mozilla-static,nsStdURLParser,necko +{7fa5237d-b0eb-438f-9e50-ca0166e63788},,application/x-mozilla-static,,necko +{3c1c0163-9bd0-11d3-9d09-0050040007b2},,application/x-mozilla-static,,nsUConvModule +{efc323e1-ec62-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{95c963b7-20b2-11db-92f6-001422106990},,text/javascript,,rel:FeedProcessor.js +{d25e0511-2bae-11d4-9d10-0050040007b2},,application/x-mozilla-static,,nsChardetModule +{b69155f4-a8bf-453d-8653-91d1456e1d3d},,text/javascript,,rel:nsTryToClose.js +{7c657d14-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eea6-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ba61519b-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{5d0ce354-df01-421a-83fb-7ead0990c24e},,text/javascript,,rel:nsBrowserContentHandler.js +{831f8f13-7aa8-485f-b02e-77c881cc5773},,application/x-mozilla-static,,necko +{660d8ca6-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{7294fe9c-14d8-11d5-9882-00c04fa02f40},,application/x-mozilla-static,,docshell_provider +{eab9012e-5f74-4cbc-b2b5-a590235513cc},,text/javascript,,rel:nsBrowserGlue.js +{ba6151a3-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{eaca2576-0d4a-11d3-9d7e-0060088f9ff7},,application/x-mozilla-static,,nsLayoutModule +{b88a4712-eb52-4c10-9b85-bf5894b510f0},,application/x-mozilla-static,,nsLayoutModule +{ba6151b2-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{0c351177-0159-4500-86b0-a219dfde4258},,application/x-mozilla-static,,nsLayoutModule +{495eca47-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{7dfdf0d1-aff6-4a34-bad1-d0fe74601642},,text/javascript,,rel:nsDownloadManagerUI.js +{da5b130a-1dd1-11b2-ad47-f455b1814a78},,application/x-mozilla-static,,nsGfxModule +{3ff8fb9f-ee63-48df-89f0-dace0242fd82},,application/x-mozilla-static,,necko +{02bf7a2a-39d8-4a23-a50c-2cbb085ab7a5},,application/x-mozilla-static,,necko +{98d41c21-ccf3-11d2-b3b1-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6803cac5-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{a62af1ba-79b3-4896-8aaf-b148bfce4280},,application/x-mozilla-static,,necko +{18c2f98d-b09f-11d2-bcde-00805f0e1353},,application/x-mozilla-static,,nsSoftwareUpdate +{fb0bbc5c-452e-4783-b32c-80124693d871},,application/x-mozilla-static,,NSS +{e3fa9d0a-1dd1-11b2-bdef-8c720b597445},,application/x-mozilla-static,,nsToolkitCompsModule +{660d8ca0-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eeb3-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ba6151b7-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{019718e3-cdb5-11d2-8d3c-000000000000},,application/x-mozilla-static,,nsLayoutModule +{7b8556a4-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{9fe5d975-09bd-44aa-a01a-66402ea28657},,application/x-mozilla-static,,mozSpellCheckerModule +{ea06d4e2-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{2d524fd8-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{c31f4883-839b-45f6-82ad-a6a9bc5ad599},,text/javascript,,rel:nsPrivateBrowsingService.js +{12bb8f17-2389-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{6b8bdffc-3394-417d-be83-a81b7c0f63bf},,application/x-mozilla-static,,docshell_provider +{ea06d4e6-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{de9472d0-8034-11d3-9399-00104ba0fd40},,application/x-mozilla-static,,necko +{c0844a84-5a12-4808-80a8-809cb002bb4f},,text/javascript,,rel:nsPlacesTransactionsService.js +{5060b803-340e-11d5-be5b-b3e063ec6a3c},,application/x-mozilla-static,,nsFindComponent +{a6cf9107-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsParserModule +{21dd6a02-413c-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{c5de4da2-d667-42d2-b8c2-efdbcf3302ef},,application/x-mozilla-static,,nsUConvModule +{57cf9383-3405-11d5-be5b-aa20fa2cf37c},,application/x-mozilla-static,,embedcomponents +{9445791f-fa4c-4669-b174-df5032bb67b3},,application/x-mozilla-static,,necko +{ccd0e960-7947-4635-b70e-4c661b63d675},,application/x-mozilla-static,,necko +{a6cf9129-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsWidgetGtk2Module +{2f977d53-5485-11d4-87e2-0010a4e75ef2},,application/x-mozilla-static,,nsWidgetGtk2Module +{d4214e92-fb94-11d2-bdd8-00104bde6048},,application/x-mozilla-static,,nsRDFModule +{c401eb80-f9ea-11d3-bb6f-e732b73ebe7c},,application/x-mozilla-static,,nsWidgetGtk2Module +{aa892eb4-ffbf-477d-9f9a-06c995ae9f27},,text/javascript,,rel:nsSearchSuggestions.js +{24f92fae-f793-473b-8061-713408bd11d5},,application/x-mozilla-native,,rel:libbrowsercomps.so +{ba6151aa-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ce02d538-0217-47a3-a589-b51790fdd8ce},,application/x-mozilla-static,,docshell_provider +{2587e382-1324-11d4-a652-eadbb2be3484},,application/x-mozilla-static,,application +{2b026890-5a2e-4981-ada2-a600358947b4},,application/x-mozilla-static,,nsUConvModule +{214c48a0-b57f-11d4-959c-0020183bf181},,application/x-mozilla-static,,docshell_provider +{74b7a390-3b41-11d4-8a80-006008c844c3},,application/x-mozilla-static,,NSS +{22117140-9c6e-11d3-aaf1-00805f8a4905},,text/javascript,,rel:nsSidebar.js +{9de95a0c-39a4-4d64-9a53-17940dd7cabb},,application/x-mozilla-static,,nsPlacesModule +{66856477-6596-40eb-bb87-59ca2dabb6f7},,application/x-mozilla-static,,nsLayoutModule +{dbded6ec-edbf-4054-a834-287b82c260f9},,text/javascript,,rel:nsBadCertHandler.js +{892ffeb0-3f80-11d3-a16c-0050041caf44},,application/x-mozilla-static,,necko +{929d9320-251e-11d4-8a7c-006008c844c3},,application/x-mozilla-static,,NSS +{1f4dbcf7-245c-4c8c-943d-8a1da0495e8a},,application/x-mozilla-static,,necko +{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980},,application/x-mozilla-native,,rel:libbrowsercomps.so +{6394eeab-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ab1da296-6125-40ba-96d0-47a8282ae3db},,application/x-mozilla-static,,nsParserModule +{d0272978-beab-4adc-a3d4-04b76acfa4e7},,text/javascript,,rel:nsPlacesAutoComplete.js +{f30bc0a2-958b-4287-bf62-ce38ba0c811e},,application/x-mozilla-static,,docshell_provider +{66634f68-be19-42d0-a4ca-d1c21fa059b8},,application/x-mozilla-static,,nsUConvModule +{2d524fd0-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{ff8780a5-bbb1-4bc5-8ee7-057e7bc5c925},,application/x-mozilla-static,,nsUConvModule +{2002f784-3960-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{2d96b3d0-c051-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsWidgetGtk2Module +{67ba681d-5485-4fff-952c-2ee337ffdcd6},,application/x-mozilla-static,,NSS +{26acb1f0-28fc-43bc-867a-a46aabc85dd4},,text/javascript,,rel:FeedProcessor.js +{ff8fe7ec-2f74-4408-b742-6b7a546029a8},,application/x-mozilla-static,,necko +{62db0002-dbb6-43f4-8fb7-9d2538bc5747},,application/x-mozilla-static,,nsComposerModule +{5b256c10-22d8-4109-af92-1253035e9fcb},,application/x-mozilla-static,,NSS +{b57f97c1-0d70-11d3-8aae-00600811a836},,application/x-mozilla-static,,nsUConvModule +{4e4aae11-8901-46cc-8217-dad7c5415873},,application/x-mozilla-static,,embedcomponents +{7b8556a9-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{439400d3-6f23-43db-8b06-8aafe1869bd8},,application/x-mozilla-static,,necko +{a578e0a4-f76b-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{9416bfb1-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{78804a84-8173-42b6-bb94-789f0816a810},@mozilla.org/network/url-parser;1?auth=no,application/x-mozilla-static,nsNoAuthURLParser,necko +{bfd1a792-ad9f-11d3-bdc7-0050040a9b44},,application/x-mozilla-static,,docshell_provider +{6803caca-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{a47e9526-6e48-4574-9d6c-3164e271f74e},,application/x-mozilla-static,,nsLayoutModule +{948a0023-e3a7-11d2-96cf-0060b0fb9956},,application/x-mozilla-static,,nsWidgetGtk2Module +{8dbe7246-1dd2-11b2-9b8f-b9a849e4403a},,application/x-mozilla-static,,necko +{8b5314ba-db01-11d2-96ce-0060b0fb9956},,application/x-mozilla-static,,nsWidgetGtk2Module +{cf7fd51f-aba2-44c1-9ff0-11f7508efcd4},,application/x-mozilla-static,,nsLayoutModule +{7d7008a0-c49a-11d3-9b22-0080c7cb1080},,application/x-mozilla-static,,necko +{77cfaaf1-1cf4-11d3-8aaf-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eeb8-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{0099907d-123c-4853-a46a-43098b5fb68c},@mozilla.org/appshell/appShellService;1,application/x-mozilla-static,AppShell Service,appshell +{cb60980e-18a5-4a77-9110-8146614ca7f0},,application/x-mozilla-static,,nsFileViewModule +{ba6151a2-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{379c2771-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{49b38f14-6193-11d3-b3c5-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{12bb8f1c-2389-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{e6fd9940-899d-11d2-8eae-00805f29f370},,application/x-mozilla-static,,nsLayoutModule +{9226888e-da08-11d3-8cda-0060b0fc14a3},@mozilla.org/network/buffered-input-stream;1,application/x-mozilla-static,nsBufferedInputStream,necko +{3a9cd622-264d-11d4-ba06-0060b0fc76dd},,application/x-mozilla-static,,nsLayoutModule +{3b581fd4-3497-426c-8f61-3658b971cb80},,application/x-mozilla-static,,nsLayoutModule +{36a1d3b3-d886-4317-96ff-87b0005cfef7},,application/x-mozilla-static,,NSS +{bf88b48c-fd8e-40b4-ba36-c7c3ad6d8ac9},,application/x-mozilla-static,,embedcomponents +{6a4d4c1e-a74a-4320-8124-16233a0183d6},,application/x-mozilla-static,,nsSoftwareUpdate +{920307b0-c6e8-11d2-8aa8-00600811a836},,application/x-mozilla-static,,nsUConvModule +{7c657d11-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eea3-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{9416bfbe-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{2bf64764-997f-450d-af96-3028d1a902b0},,application/x-mozilla-static,,nsI18nModule +{fcacef23-2b40-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{0885d4f8-f7b8-4cda-902e-94ba38bc256e},,application/x-mozilla-static,,necko +{a380e9c0-cb39-11da-a94d-0800200c9a66},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-service.js +{7c02eadc-0076-4d03-998d-80d779c48589},,application/x-mozilla-static,,nsSecurityManagerModule +{895db6c7-dbdf-40ea-9f64-b175033243dc},,application/x-mozilla-static,,satchel +{78481e4a-50e4-4489-b68a-ef82670ed63f},,application/x-mozilla-native,,rel:libbrowsercomps.so +{e12752f0-ee9a-11d1-a82a-0040959a28c9},,application/x-mozilla-static,,nsGfxModule +{47049e42-1d87-482a-984d-56ae185e367a},,application/x-mozilla-static,,nsChromeModule +{8df290ae-dcaa-4c11-98a5-2429a4dc97bb},,text/javascript,,rel:nsContentPrefService.js +{ba6151af-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ffc08380-256c-11d5-9905-001083010e9b},,application/x-mozilla-native,,rel:libimgicon.so +{376ff2c1-9bf6-418a-b143-3340c00112f7},,application/x-mozilla-static,,nsImageLib2Module +{495eca44-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{972d8d8f-f0da-11d4-9885-00c04fa0cf4b},,application/x-mozilla-static,,nsLayoutModule +{56388dad-287b-4240-a785-85c394012503},,application/x-mozilla-static,,necko +{0f78da56-8321-11d2-8eac-00805f29f370},,application/x-mozilla-static,,nsRDFModule +{e56f5e01-c7cc-4675-a9d7-b8f1e4127295},,application/x-mozilla-static,,docshell_provider +{6394eec0-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{0404d02a-01ca-aaab-4762-944b1bf2f7b5},,application/x-mozilla-static,,nsLayoutModule +{a35d1cd4-c505-4d2d-a0f9-aef00b7ce5a5},,application/x-mozilla-static,,nsLayoutModule +{0032d852-1dd2-11b2-95f7-e0a1910ed2da},,application/x-mozilla-static,,nsRDFModule +{0a3be523-0f2a-32cc-ccd8-1e5986d5a79d},,text/javascript,,rel:GPSDGeolocationProvider.js +{87ed1160-e2f2-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{6394eeb0-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7b8556a1-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{0cb0d9a0-f503-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{a59da935-4091-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{3f6fe6a2-ac0a-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{2d524fd5-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{6f8366c7-2195-42ce-a149-48e26aeb9c24},,application/x-mozilla-static,,nsLayoutModule +{e332db00-e076-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{3decd6c8-30ef-11d3-8cd0-0060b0fc14a3},,application/x-mozilla-static,,necko +{e8b8bdb7-c96c-4d82-9c6f-2b3c585ec7ea},,application/x-mozilla-static,,nsPlacesModule +{f1eac762-87e9-11d3-af80-00a024ffc08c},,application/x-mozilla-static,,docshell_provider +{ba6151bc-ec62-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7},,text/javascript,,rel:nsContentPrefService.js +{2e9b69dd-9087-438c-8b5d-f77b553abefb},,application/x-mozilla-static,,docshell_provider +{e64f152a-9f07-11d3-8cda-0060b0fc14a3},@mozilla.org/network/protocol;1?name=resource,application/x-mozilla-static,nsResProtocolHandler,necko +{26a4a019-2827-4a89-a85c-5931a678823a},,text/javascript,,rel:nsUrlClassifierLib.js +{4a6212db-accb-11d3-b765-0060b0b6cecb},,application/x-mozilla-static,,nsSecurityManagerModule +{bbbb1d61-438f-4436-92ed-8308e5830fb0},,application/x-mozilla-static,,mozStorageModule +{7319788a-fe93-4db3-9f39-818cf08f4256},,text/javascript,,rel:nsSearchService.js +{841387c8-72e6-484b-9296-bf6eea80d58a},,application/x-mozilla-static,,nsWidgetGtk2Module +{7fbd2146-5ff4-4674-b069-a7bbce66e773},,application/x-mozilla-static,,nsComposerModule +{d0f9db12-249c-11d5-9905-001083010e9b},,application/x-mozilla-native,,rel:libimgicon.so +{6803cacf-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{ed0244e0-c144-11d2-8f4c-006008159b0c},,application/x-mozilla-static,,nsLayoutModule +{14632191-ac21-4bdf-83e7-2363ad17e838},,application/x-mozilla-static,,nsLayoutModule +{a6cf9126-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{5f43022c-6194-4b37-b26d-e41024625264},,application/x-mozilla-native,,rel:libmozgnome.so +{4d977f60-fbe7-4583-8cb7-f5ed882293ef},,application/x-mozilla-static,,nsLayoutModule +{c2710d40-6f4d-4b7f-9778-76ae5166648c},,application/x-mozilla-static,,nsLayoutModule +{6394eebd-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7b8556ae-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{379c2776-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{ea617873-3b73-4efd-a2c4-fc39bfab809d},,application/x-mozilla-static,,necko +{db340cc2-7f50-4ea3-8427-f529daf6dc87},,application/x-mozilla-static,,satchel +{f6d5ebbd-34f4-487d-9d10-3d34123e3eb9},,application/x-mozilla-static,,tkAutoCompleteModule +{6987230e-0098-4e78-bc5f-1493ee7519fa},,application/x-mozilla-static,,nsWidgetGtk2Module +{f01cb3e7-4ace-414e-a2b7-eaba03e9c86c},,application/x-mozilla-static,,nsUCvMathModule +{af7a9952-aa48-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{8c2023b9-175c-477e-9761-44ae7b549756},,text/javascript,,rel:storage-mozStorage.js +{4ca6b67b-5cc7-4e71-a98a-97af1c134862},,application/x-mozilla-static,,nsPermissionsModule +{64f300a1-c88c-11d3-97fb-00400553eef0},,application/x-mozilla-static,,nsLayoutModule +{a4bd2161-7892-4389-8d5a-3111a6d17ec7},,application/x-mozilla-static,,PKI +{66230b2b-17fa-4bd3-abf4-07986151022d},,application/x-mozilla-static,,necko +{1dcc23b0-d4cb-11dc-9ad6-479d56d89593},,text/javascript,,rel:nsTaggingService.js +{5d0fcdd0-4daa-11d2-b328-00805f8a3859},,application/x-mozilla-static,,nsLayoutModule +{a431b276-f77d-4b83-9b37-872cf2fbcc2a},,application/x-mozilla-static,,nsUConvModule +{8f666a11-04a0-11d3-b3b9-00805f8a6670},,application/x-mozilla-static,,nsI18nModule +{1cd91b88-1dd2-11b2-92e1-ed22ed298000},@mozilla.org/preferences-service;1,application/x-mozilla-static,Preferences Server,nsPrefModule +{dab3a846-3a59-4fc2-9745-c6ff48776f00},,application/x-mozilla-static,,mozStorageModule +{6394eea8-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{0958b101-9ada-11d2-8ebc-00805f29f370},,application/x-mozilla-static,,nsRDFModule +{9158c470-86e4-11d4-9be2-00e09872a416},,application/x-mozilla-static,,necko +{b9507aec-1dd1-11b2-8cd5-c48ee0c50307},,application/x-mozilla-static,,NSS +{c64d0bcb-8270-4ca7-a0b3-3380c8ffecb5},,text/javascript,,rel:nsSafebrowsingApplication.js +{b6ed3030-6183-11d3-a178-0050041caf44},,application/x-mozilla-static,,necko +{c07e81e0-ef12-11d2-92b6-00105a1b0d64},@mozilla.org/network/socket-transport-service;1,application/x-mozilla-static,nsSocketTransportService,necko +{64d6174c-1496-4ffd-87f2-da2670f88934},,application/x-mozilla-static,,mozSpellCheckerModule +{fb5c1775-1bbd-4b9c-abb0-ae7acd29e87e},,application/x-mozilla-static,,nsLayoutModule +{2002f781-3960-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{1f34bc80-1bc7-11d6-a384-d705dd0746fc},,application/x-mozilla-static,,nsLayoutModule +{ba61519a-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{8b042e22-6f87-11d3-b3c8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{4dc30689-929d-425e-a709-082c6294e542},,application/x-mozilla-static,,nsLayoutModule +{ba6151b4-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{660d8ca5-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{4f6b5e00-0c36-11d5-a535-0010a401eb10},,application/x-mozilla-static,,nsCookieModule +{495eca49-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{a578e0a1-f76b-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{aeb8936f-219c-4d3c-8385-d9382daa551a},,application/x-mozilla-static,,mozSpellCheckerModule +{bacd8ad0-552f-11d3-a9f7-000064657374},,application/x-mozilla-static,,nsLayoutModule +{6803cac7-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{0bec75a8-1dd2-11b2-863a-f69f77c31371},,application/x-mozilla-static,,PKI +{d5eb483c-67c0-4286-a4a6-330e58a82300},,application/x-mozilla-static,,nsUCvMathModule +{9286e71a-621a-4b91-851e-9984c1a2e81a},,application/x-mozilla-static,,nsLayoutModule +{0704e7c0-a758-11d2-9119-006008a6edf6},,application/x-mozilla-static,,nsI18nModule +{4aef38b7-6364-4e23-a5e7-12f837fbbd9c},,application/x-mozilla-static,,nsLayoutModule +{660d8ca2-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eeb5-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7b8556a6-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{ba61519f-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{5d5d92cd-6bf8-11d9-bf4a-000a95dc234c},,application/x-mozilla-static,,nsLayoutModule +{2d524fda-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{7baf62e0-8e61-11d2-8eb1-00805f29f370},,application/x-mozilla-static,,nsRDFModule +{136e2c4d-c5a4-477c-b131-d93d7d704f64},@mozilla.org/privatebrowsing-wrapper;1,application/x-mozilla-native,PrivateBrowsing Service C++ Wrapper,rel:libbrowsercomps.so +{0f2f347c-1e4f-40cc-8efd-792dea70a85e},,text/javascript,,rel:nsLoginInfo.js +{2ee83680-2af0-4bcb-bfa0-c9705f6554f1},,application/x-mozilla-static,,docshell_provider +{414af362-9ad8-4296-898e-62247f25a20e},,text/javascript,,rel:FeedProcessor.js +{2d524fdd-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{aaab6710-0f2c-11d5-a53b-0010a401eb10},,application/x-mozilla-static,,necko +{e9b301c0-e0e4-11d3-a1a8-0050041caf44},,application/x-mozilla-static,,necko +{23e8fd98-a625-4b08-be1a-f7cc18a5b106},,application/x-mozilla-static,,nsPluginModule +{77cfaaf2-1cf4-11d3-8aaf-00600811a836},,application/x-mozilla-static,,nsUConvModule +{d9b1f97e-cfa0-80b6-fb92-9972e48e3dcc},,application/x-mozilla-static,,nsUConvModule +{929814d6-1dd2-11b2-8e08-82fa0a339b00},,application/x-mozilla-static,,xpconnect +{ba5bc4c6-1dd1-11b2-bb89-b844c6ec0339},,application/x-mozilla-static,,nsAutoConfigModule +{e7caf8c0-3570-47fe-aa1b-da47539b5d07},,application/x-mozilla-static,,NSS +{ea06d4e5-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{2f277c00-0eaf-4ddb-b936-41326ba48aae},,application/x-mozilla-static,,necko +{1423e739-782c-4081-b5d8-fe6fba68c0ef},,application/x-mozilla-static,,necko +{e042570c-62de-4bb6-a6e0-798e3c07b4df},,application/x-mozilla-static,,embedcomponents +{0ae53c0f-8ea2-4916-bedc-717443c3e185},,application/x-mozilla-static,,NSS +{0ddf4df8-4dbb-4133-8b79-9afb966514f5},,application/x-mozilla-static,,nsLayoutModule +{0de2fbfa-6b7f-11d7-bbba-0003938a9d96},,application/x-mozilla-static,,nsLayoutModule +{ba6151ac-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{cb3ede1a-0fa5-4e27-aafe-0f7801e5a1f1},,application/x-mozilla-static,,nsImageLib2Module +{5aaeb534-fa57-488d-9a73-20c258fc7bdb},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-channel-listener.js +{c94f4a30-64d7-11d4-9960-00b0d02354a0},,application/x-mozilla-static,,NSS +{56ad2981-8a87-11d2-918c-0080c8e44db5},,application/x-mozilla-static,,nsLayoutModule +{822bcd11-6432-48be-9e9d-36f7804b7747},,application/x-mozilla-static,,nsCookieModule +{6ddb050c-0d04-11d4-986e-00c04fa0cf4a},,application/x-mozilla-static,,necko +{1691e1f4-ee41-11d4-9885-00c04fa0cf4b},,application/x-mozilla-static,,nsLayoutModule +{379c2774-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{a6cf90f5-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{49bb6593-3aff-4eb3-a068-2712c28bd58e},,text/javascript,,rel:FeedWriter.js +{e6156350-2be8-11db-a98b-0800200c9a66},,text/javascript,,rel:nsURLFormatter.js +{6394eead-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{42c52b81-a200-11d3-9d0b-0050040007b2},,application/x-mozilla-static,,nsXPIntlModule +{32314cc8-22f7-4f7f-a645-1a45453ba6a6},,text/javascript,,rel:nsHandlerService.js +{a59da932-4091-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{bfcb82c2-5611-4318-90d6-baf4a7864252},,application/x-mozilla-static,,nsLayoutModule +{9d3f70da-86e9-11d4-95ec-00b0d03e37b7},,application/x-mozilla-static,,nsLayoutModule +{2d524fd2-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{a2112d6a-0e28-421f-b46a-25c0b308cbd0},,application/x-mozilla-static,,embedcomponents +{2ce606b0-bee6-11d1-aad9-00805f8a3e14},,application/x-mozilla-static,,nsParserModule +{7526a738-9632-11d3-8cd9-0060b0fc14a3},,application/x-mozilla-static,,nsJarModule +{ff8c4d10-3194-11d3-9885-006008962422},@mozilla.org/js/xpc/ContextStack;1,application/x-mozilla-static,,xpconnect +{d2800356-c2d7-4e05-a884-79fe566af1cf},,application/x-mozilla-static,,nsUConvModule +{9868b4ce-da08-11d3-8cda-0060b0fc14a3},@mozilla.org/network/buffered-output-stream;1,application/x-mozilla-static,nsBufferedOutputStream,necko +{ba6151b9-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{d9b1f97f-cfa0-80b6-fb92-9972e48e3dcc},,application/x-mozilla-static,,nsUConvModule +{bc54f001-6eb0-4e32-9f49-7e064d8e70ef},,application/x-mozilla-static,,nsAuthModule +{26fb965c-9de6-11d3-bccc-0060b0fc76bd},,application/x-mozilla-static,,nsLayoutModule +{2d78bbf0-e26c-482b-92b3-78a7b2afc8f7},,application/x-mozilla-static,,nsLayoutModule +{62b778a6-bce3-456b-8c31-2865fbb68c91},@mozilla.org/network/idn-service;1,application/x-mozilla-static,nsIDNService,necko +{9416bfb3-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6030f7ef-32ed-46a7-9a63-6a5d3f90445f},,application/x-mozilla-static,,nsLayoutModule +{e7c2aaf5-c11a-4954-9dbf-e28edec1fd91},,application/x-mozilla-static,,nsLayoutModule +{6803cacc-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{9f6d5d40-90e7-11d3-af80-00a024ffc08c},,application/x-mozilla-static,,docshell_provider +{8b5314bc-db01-11d2-96ce-0060b0fb9956},,application/x-mozilla-static,,nsWidgetGtk2Module +{660d8ca7-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{7b8556a2-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{bd1326a6-5a14-48de-97cc-95b5195f4fb9},,application/x-mozilla-static,,nsUCvMathModule +{ba6151a4-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{75c80fd0-accb-432c-af59-ec60668c3990},,application/x-mozilla-static,,nsAuthModule +{6deb193c-f87d-4078-bc78-5e64655b4d62},,application/x-mozilla-native,,rel:libbrowserdirprovider.so +{44588c1f-2ce8-4ad8-9b16-dfb9d9d513a7},,application/x-mozilla-static,,necko +{45c23a20-d71c-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{a6cf9112-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsParserModule +{f916ebfb-78ef-464b-94d0-a6f2ca3200ae},,application/x-mozilla-static,,nsWidgetGtk2Module +{2d92593e-14d0-48ce-b260-a9881bbf9c8b},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-http-observer.js +{c6e8c44d-9f39-4af7-bcc0-76e38a8310f5},,text/javascript,,rel:nsBrowserGlue.js +{0e4e7d00-f71a-439f-9178-1a71ff11b55f},,application/x-mozilla-static,,nsLayoutModule +{7b8556b2-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{7c657d13-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eea5-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{9416bfc0-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{2e363d60-872e-11d2-b531-000000000000},,application/x-mozilla-static,,nsLayoutModule +{d930e29b-6909-44e5-ab4b-af10d6923705},,application/x-mozilla-static,,nsWidgetGtk2Module +{a1b72850-a999-11d2-9119-006008a6edf6},,application/x-mozilla-static,,nsI18nModule +{3a0a0fc1-8349-11d3-be47-00104bde6048},,application/x-mozilla-static,,nsLayoutModule +{6049b263-c1e6-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsGfxModule +{670ee5da-6ad5-11d7-9950-000393636592},,application/x-mozilla-static,,embedcomponents +{ec693a6f-0832-49dd-877c-89f6552df5de},,application/x-mozilla-static,,NSS +{dccbe7e4-7750-466b-a557-5ea36c8ff24e},,application/x-mozilla-static,,necko +{1f59b001-02c9-11d5-ae76-cc92f7db9e03},,application/x-mozilla-static,,embedcomponents +{18a03189-067b-4978-b4f1-bafe35292ed6},,text/javascript,,rel:txEXSLTRegExFunctions.js +{ba6151b1-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{47433d1d-d9a7-4954-994f-f7a05cf87c2e},,application/x-mozilla-static,,nsUConvModule +{84e11f80-ca55-11dd-ad8b-0800200c9a66},,application/x-mozilla-native,,rel:libmozgnome.so +{495eca46-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{0e6892c1-a9ad-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{d4214e93-fb94-11d2-bdd8-00104bde6048},,application/x-mozilla-static,,nsRDFModule +{58f089ee-512a-42d2-a935-d0c874128930},,application/x-mozilla-static,,nsLayoutModule +{6316c6ce-12d3-479e-8f53-e289351412b8},@mozilla.org/intl/stringbundle/text-override;1,application/x-mozilla-static,String Textfile Overrides,nsI18nModule +{6803cac4-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{34587f4a-be18-43c0-9112-b782b08c0add},,application/x-mozilla-static,,BOOT +{5ba6d920-d4e9-11d3-a1a5-0050041caf44},,application/x-mozilla-static,,necko +{822cb9ae-6421-4484-b3c3-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6803cac9-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{1b117e16-0cad-11d4-986e-00c04fa0cf4a},,application/x-mozilla-static,,nsJarModule +{4b664e54-72a2-4bbf-a5c2-66d4dc3066a0},,application/x-mozilla-static,,nsLayoutModule +{8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f},,text/javascript,,rel:FeedProcessor.js +{6394eeb2-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6803cacd-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{b992ddcd-3899-4320-9909-924b3e72c922},,text/javascript,,rel:FeedProcessor.js +{7b8556a3-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{471f4944-1dd2-11b2-87ac-90be0a51d609},,application/x-mozilla-static,,embedcomponents +{14c13684-1dd2-11b2-9463-bb10ba742554},,application/x-mozilla-static,,nsToolkitCompsModule +{9c7ec5d1-23f9-11d5-aea8-8fcc0793e97f},,application/x-mozilla-static,,necko +{2d524fd7-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{b148eed2-236d-11d3-b35c-00a0cc3c1cde},,application/x-mozilla-static,,nsWidgetGtk2Module +{12bb8f16-2389-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{ed394ba0-5472-11d3-bbc8-0000861d1237},,application/x-mozilla-static,,necko +{e638d761-8687-11d2-b530-000000000000},,application/x-mozilla-static,,nsRDFModule +{762c4ae7-b923-422f-b97e-b9bfc1ef7bf0},,application/x-mozilla-static,,nsLayoutModule +{9e9b565a-8e52-4c1a-8805-b2b91655f874},,application/x-mozilla-static,,nsI18nModule +{057b04d0-0ccf-11d2-beba-00805f8a66dc},,application/x-mozilla-static,,docshell_provider +{0a698c44-3bff-11d4-9649-00c0ca135b4e},,application/x-mozilla-static,,nsUConvModule +{bfd1a791-ad9f-11d3-bdc7-0050040a9b44},,application/x-mozilla-static,,docshell_provider +{36102b6b-7b62-451a-a1c8-a0d456c92dc5},,application/x-mozilla-static,,nsSecurityManagerModule +{63c7b9f4-0cc8-43f8-b666-0a661655cb73},,application/x-mozilla-native,,rel:libbrowsercomps.so +{8aa66d77-1bbb-45a6-991e-b8f47751c291},,text/javascript,,rel:nsLoginManagerPrompter.js +{9eb760f0-4380-11d2-b328-00805f8a3859},,application/x-mozilla-static,,nsLayoutModule +{2e41ada0-62b7-4902-b9a6-e4542aa458ba},,application/x-mozilla-static,,embedcomponents +{320706d2-2e81-42c6-89c3-8d83b17d3fb4},,application/x-mozilla-static,,necko +{9589dc0d-9709-4578-883e-d393452b3611},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-annotations.js +{1f5c1721-7dc3-11d3-bf87-00105a1b0627},,application/x-mozilla-static,,nsLayoutModule +{f1eac761-87e9-11d3-af80-00a024ffc08c},,application/x-mozilla-static,,Browser_Embedding_Module +{40b22006-5dd5-42f2-bfe7-7dbf0757ab8b},,application/x-mozilla-static,,nsLayoutModule +{9ef9fa14-1dd1-11b2-9d65-d72d6d1f025e},,application/x-mozilla-static,,necko +{5632bf70-51ec-11d3-9896-006008962422},@mozilla.org/js/xpc/Exception;1,application/x-mozilla-static,,xpconnect +{36b63ef3-e0fa-4c49-9fd4-e065e85568f4},,application/x-mozilla-static,,necko +{6394eebf-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ba6151a9-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{379c2778-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{dc8e21a0-03e4-11da-8cd6-0800200c9a66},,application/x-mozilla-static,,nsAuthModule +{17491ba4-1dd2-11b2-aae3-de6b92dab620},,application/x-mozilla-static,,necko +{d6008c40-4dad-11d2-b328-00805f8a3859},,application/x-mozilla-static,,nsLayoutModule +{3a8a3a50-512c-11d4-9a54-000064657374},,application/x-mozilla-static,,nsLayoutModule +{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0},,text/javascript,,rel:FeedConverter.js +{54ae32f8-1dd2-11b2-a209-df7c505370f8},,text/javascript,,rel:nsFilePicker.js +{9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7},,application/x-mozilla-static,,nsImageLib2Module +{94f1de09-d0e5-4ca8-94c2-98b049316b7f},,application/x-mozilla-static,,nsSystemPrefModule +{a4557478-ae16-11d5-ba4b-00108303b117},,application/x-mozilla-static,,NSS +{adf42751-1cef-4ad2-aa8e-bcb849d8d31f},,application/x-mozilla-static,,nsI18nModule +{a39e0e9d-e567-41e3-b12c-5df67f18174d},,application/x-mozilla-static,,NSS +{fb8cbf4e-4701-4ba1-b1d6-5388e041fb67},,application/x-mozilla-static,,necko +{feca3c34-205e-4ae5-bd1c-03c686ff012b},,application/x-mozilla-static,,nsLayoutModule +{7c657d18-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{f66bc334-1dd1-11b2-bab2-90e04fe15c19},,application/x-mozilla-static,,Browser_Embedding_Module +{a772eee4-0464-405d-a329-a29dfda3791a},,application/x-mozilla-static,,docshell_provider +{3a449110-66fd-11d4-9528-0020183bf181},,application/x-mozilla-static,,Browser_Embedding_Module +{6fb0c970-e1b1-11db-8314-0800200c9a66},,application/x-mozilla-native,,rel:libbrowsercomps.so +{b5e65b52-1dd1-11b2-ae8f-f0928ed88482},@mozilla.org/js/xpc/RuntimeService;1,application/x-mozilla-static,,xpconnect +{38d1592e-b81e-432b-86f8-471878bbfe07},,application/x-mozilla-static,,nsImageLib2Module +{01e1c3ff-094a-d048-44b4-62d29c7b4f39},,application/x-mozilla-static,,nsLayoutModule +{0fa3158c-d5a7-43de-9181-a285e74cf1d4},,application/x-mozilla-static,,nsUnixProxyModule +{2002f783-3960-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{6ebc941a-f2ff-4d56-b3b6-f7d0b9d73344},,text/javascript,,rel:nsDefaultCLH.js +{1abdcc96-1dd2-11b2-b520-f8f59cdd67bc},,application/x-mozilla-static,,nsLayoutModule +{e09af32d-2a54-4d76-9ef0-3070e83f8be7},,application/x-mozilla-static,,nsLayoutModule +{a665e49a-f3e6-4fed-9f31-f7c568a29899},@mozilla.org/intl/unicodenormalizer;1,application/x-mozilla-static,Unicode Normlization,nsI18nModule +{ba6151b6-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{cf0f71fd-fafd-4e2b-9fdc-134d972e16e2},,application/x-mozilla-static,,necko +{5fb907e0-1dd2-11b2-a7c0-f14c416a62a1},,application/x-mozilla-static,,NSS +{0c797702-1c60-4051-9dd7-4d7405605642},,application/x-mozilla-static,,jsctypes +{13e50d8d-9cee-4ad1-a3a2-4a442fdf7dfa},,application/x-mozilla-static,,nsComposerModule +{a1fde867-e802-11d4-9885-00c04fa0cf4b},,application/x-mozilla-static,,nsLayoutModule +{a578e0a3-f76b-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{f96f5ec9-755b-447e-b1f3-717d1a84bb41},,application/x-mozilla-static,,nsLayoutModule +{776588a6-86d5-47e2-b6b3-992810078202},,application/x-mozilla-static,,nsUConvModule +{f6913e2e-1dd1-11b2-84be-f455dee342af},,application/x-mozilla-static,,necko +{a6cf9120-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsI18nModule +{06aa7c21-fe05-4cf2-b1c4-0c7126a4f713},,application/x-mozilla-static,,nsLayoutModule +{ba61519d-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{660d8ca4-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eeb7-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{69bb8313-2d4f-45ec-97e0-d39da58ecce9},,text/javascript,,rel:nsExtensionManager.js +{7b8556a8-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{ba6151a1-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{830b5f80-e2f2-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{2d524fdc-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{cc10c750-9ec3-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsI18nModule +{12bb8f1b-2389-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{d9783472-8fe9-11d2-9d3c-0060088f9ff7},,application/x-mozilla-static,,nsLayoutModule +{09f689e0-b4da-11d2-a68b-00104bde6048},,application/x-mozilla-static,,nsLayoutModule +{eae599aa-ecef-49c6-a8af-6ddcc6feb484},,application/x-mozilla-static,,NSS +{fcca6f83-9f7d-44e4-a74b-b59433e6c8c3},,application/x-mozilla-static,,nsLayoutModule +{e09e4ca6-276b-4bb4-8b71-0635a3a2a007},,text/javascript,,rel:storage-Legacy.js +{218f2ac0-0a48-11d3-b3ba-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{51fa28c7-74c0-4b85-9c46-d03faa7b696b},,application/x-mozilla-static,,necko +{663ca4a8-d219-4000-925d-d8f66406b626},,application/x-mozilla-static,,nsAccessibilityModule +{6394eea2-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{bfd05264-834c-11d2-8eac-00805f29f370},,application/x-mozilla-static,,nsRDFModule +{ca200860-4696-40d7-88fa-4490d423a8ef},,application/x-mozilla-static,,embedcomponents +{2bc2ad62-ad5d-4b7b-a9db-f74ae203c527},,application/x-mozilla-static,,nsUConvModule +{1f1ce501-663a-11d3-b7a0-be426e4e69bc},,application/x-mozilla-static,,appshell +{3f429a14-dffe-417d-8cb8-fdf09bacd09e},,application/x-mozilla-static,,NSS +{a2059c0e-5a58-4c55-ab7c-26f0557546ef},,application/x-mozilla-static,,satchel +{a61e6398-2057-40fd-9c81-873b908d24e7},,application/x-mozilla-static,,nsWidgetGtk2Module +{8d995d4f-adcc-4159-b7f1-e94af72eeb88},,application/x-mozilla-static,,BOOT +{2ee3039b-2de4-43d9-93b0-649beacff39a},,application/x-mozilla-static,,tkAutoCompleteModule +{75a500a2-0030-40f7-86f8-63f225b940ae},,application/x-mozilla-native,,rel:libdbusservice.so +{67671792-8e25-4487-b1b7-5073cfa95fee},,application/x-mozilla-static,,nsUCvMathModule +{ba6151ae-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{1f13b201-39fa-11d6-a7f2-df501ff820dc},,application/x-mozilla-static,,nsLayoutModule +{ea06d4e1-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{a3254cb0-8e20-11d2-8a98-00600811a836},,application/x-mozilla-static,,nsUConvModule +{9dcef3a4-a3bc-11d5-ba47-00108303b117},,application/x-mozilla-static,,NSS +{ac9e3e82-bfbd-4f26-941e-f58c8ee178c1},,application/x-mozilla-static,,nsLayoutModule +{9e3b6c90-2f75-11d3-8cd0-0060b0fc14a3},,application/x-mozilla-static,,necko +{7dd4d320-c84b-4624-8d45-7bb9b2356977},,application/x-mozilla-static,,nsToolkitCompsModule +{374e0cde-f605-4259-8c92-e639c6c2eeef},,application/x-mozilla-static,,nsUniversalCharDetModule +{2a898043-180f-4c8b-8e54-410c7a540f27},,application/x-mozilla-static,,nsWidgetGtk2Module +{2376201c-bbc6-472f-9b62-7548040a61c6},,text/javascript,,rel:FeedConverter.js +{e0da1d70-2f7b-11d3-8cd0-0060b0fc14a3},,application/x-mozilla-static,,necko +{a181af0d-68b8-4308-94db-d4f859058215},,application/x-mozilla-static,,necko +{461cd5dd-73c6-47a4-8cc3-603b37d84a61},,application/x-mozilla-static,,ZipWriterModule +{5534ddc0-dd96-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{84b0f182-c6c7-11d2-b3b0-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6394eeaf-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{460a9792-b154-4f26-a922-0f653e2c8f91},,text/javascript,,rel:nsMicrosummaryService.js +{a2027ec6-ba0d-4c72-805d-148233f5f33c},,application/x-mozilla-static,,necko +{ba615199-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{495eca43-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{3f6fe6a1-ac0a-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{296d76aa-275b-4f3c-af8a-30a4026c18fc},,application/x-mozilla-static,,NSS +{2d524fd4-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{a6cf90e5-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{77c0e42a-1dd2-11b2-8ebf-edc6606f2f4b},,application/x-mozilla-static,,necko +{7bb40992-77eb-43db-9a4e-39d3bcc383ae},,application/x-mozilla-static,,nsParserModule +{8a0dce80-e2f2-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{a4048e94-1dd1-11b2-a676-8a06c086cc7d},,application/x-mozilla-static,,nsRDFModule +{549abb24-7c9d-4aba-915e-7ce0b716b32f},,application/x-mozilla-static,,nsSystemPrefModule +{815e42e0-72cc-480f-934b-148e33c228a6},,application/x-mozilla-static,,nsAuthModule +{ba6151bb-ec62-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{95f46161-d177-11d2-bf86-00105a1b0627},,application/x-mozilla-static,,nsLayoutModule +{072a5c3d-30c6-4f07-b87f-9f63d51403f2},,text/javascript,,rel:FeedProcessor.js +{e1c61582-2a84-11d3-8cce-0060b0fc14a3},,application/x-mozilla-static,,necko +{a0f827e2-8ab6-11d5-a14b-005004832142},,application/x-mozilla-static,,nsUConvModule +{6803cace-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{1c31ed79-accd-4b94-b517-06e0c81999d5},,text/javascript,,rel:FeedConverter.js +{2f977d4f-5485-11d4-87e2-0010a4e75ef2},,application/x-mozilla-static,,nsPrefModule +{fe74cf80-aa2d-11db-abbd-0800200c9a66},,text/javascript,,rel:fuelApplication.js +{d2ac51bc-1622-4d4d-85cb-f8e8b5805cb9},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components/firebug-trace-service.js +{660d8ca9-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eebc-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7b8556ad-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{379c2775-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{a4e5888f-4fe4-4632-8e7e-745196ea7c70},,application/x-mozilla-static,,NSS +{541afcb2-a9a3-11d2-8ec5-00805f29f370},,application/x-mozilla-static,,nsLayoutModule +{bfd0526d-834c-11d2-8eac-00805f29f370},,application/x-mozilla-static,,nsRDFModule +{4f47e42e-4d23-4dd3-bfda-eb29255e9ea3},,application/x-mozilla-static,,necko +{64edb481-0c04-11d5-a73c-e964b968b0bc},,application/x-mozilla-static,,embedcomponents +{7e677795-c582-4cd1-9e8d-8271b3474d2a},,application/x-mozilla-static,,embedcomponents +{af7a9951-aa48-11d2-b3ae-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{797bec5a-1dd2-11b2-a7f8-ca397e0179c4},,application/x-mozilla-static,,nsImageLib2Module +{27aecc62-7777-428e-b34c-5973a47b8298},,application/x-mozilla-static,,nsLayoutModule +{d96d5985-a13a-4bdc-9386-ef348d7a97a1},,application/x-mozilla-native,,rel:libmozgnome.so +{efc323e2-ec62-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{fca3766a-434a-4ae7-83cf-0909e18a093a},,application/x-mozilla-static,,necko +{95d89e3e-a169-41a3-8e56-719978e15b12},@mozilla.org/xre/app-info;1,application/x-mozilla-static,nsXULAppInfo,Apprunner +{fcacef22-2b40-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{9ac9e770-18bc-11d3-9337-00104ba0fd40},@mozilla.org/network/io-service;1,application/x-mozilla-static,nsIOService,necko +{7c657d15-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{edb0490e-1dd1-11b2-83b8-dbf8d85906a6},,application/x-mozilla-static,,nsToolkitCompsModule +{6394eea7-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{a21bfa01-f349-4394-a84c-8de5cf0737d0},,application/x-mozilla-static,,embedcomponents +{63ac8c66-1dd2-11b2-b070-84d00d3eaece},,text/javascript,,rel:nsProxyAutoConfig.js +{ba615191-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{fe4f7592-c1fc-4662-ac83-538841318803},,application/x-mozilla-static,,xpconnect +{fc2389b8-c650-4093-9e42-b05e5f0685b7},,application/x-mozilla-static,,nsWidgetGtk2Module +{58a1c31c-1dd2-11b2-a3f6-d36949d48268},,application/x-mozilla-static,,necko +{c7e410d4-85f2-11d3-9f63-006008a6efe9},,application/x-mozilla-static,,nsJarModule +{4ca3c946-5408-49f0-9eca-3a97d5c67750},,application/x-mozilla-native,,rel:libbrowsercomps.so +{7b8556b1-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{7ee2a4c0-4b93-17d3-ba18-0060b0f199a2},@mozilla.org/scriptsecuritymanager;1,application/x-mozilla-static,scriptsecuritymanager,nsSecurityManagerModule +{ba6151b3-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ca168834-cc00-48f9-b83c-fd018e58cae3},,text/javascript,,rel:nsUrlClassifierListManager.js +{ec7a6c20-e081-11da-8ad9-0800200c9a66},,text/javascript,,rel:nsSessionStartup.js +{77221d5a-1dd2-11b2-8c69-c710f15d2ed5},,application/x-mozilla-static,,nsWidgetGtk2Module +{5280606b-2510-4fe0-97ef-9b5a22eafe6b},,text/javascript,,rel:nsSessionStore.js +{495eca48-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{6049b262-c1e6-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsGfxModule +{b00ed78a-04e2-4f74-8e1c-d1af79dfd12f},,application/x-mozilla-static,,necko +{bfd05264-834c-11d2-8eac-00805f29f371},,application/x-mozilla-static,,nsLayoutModule +{e746a8b1-c97a-4fc5-baa4-66607521bd08},,application/x-mozilla-static,,necko +{a6cf9063-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{6803cac6-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{fcacef21-2b40-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{518e071f-1dd2-11b2-937e-c45f14def778},,application/x-mozilla-static,,PKI +{f24a14f0-4fa1-11d3-9894-006008962422},,application/x-mozilla-static,,xpconnect +{e35d5067-95bc-4029-8432-e8f1e431148d},,text/javascript,,rel:nsContentDispatchChooser.js +{660d8ca1-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eeb4-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{14c0e880-623e-11d3-a178-0050041caf44},,application/x-mozilla-static,,necko +{7a2a7a56-827f-4b38-bdac-31aa7ec2971d},,text/javascript,,abs:/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/components/aboutHome.js +{ba61519e-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{4f5e62b8-d659-4156-84fc-2f6099400369},,application/x-mozilla-static,,nsLayoutModule +{6c84aec9-29a5-4264-8fbc-bee8f922ea67},,application/x-mozilla-static,,necko +{2d524fd9-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{47cd0651-b1be-4a0f-b5c4-10e5a573ef71},,text/javascript,,rel:nsBrowserContentHandler.js +{e91f9440-e076-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{06beec76-a183-4d9f-85dd-085f26da565a},,application/x-mozilla-static,,nsWidgetGtk2Module +{8a115faa-7dcb-4e8f-979b-5f53472f51cf},,text/javascript,,rel:nsExtensionManager.js +{fd9a9e8a-a77b-496a-b7bb-263df9715149},,application/x-mozilla-static,,nsImageLib2Module +{e7f70966-9a37-48d7-8aeb-35998f31090e},,application/x-mozilla-static,,nsToolkitCompsModule +{a0ccaaf8-09da-44d8-b250-9ac3e93c8117},,application/x-mozilla-static,,nsToolkitCompsModule +{21dd6a03-413c-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{ecba5203-77da-465a-865e-78b7af10d8f7},,application/x-mozilla-static,,nsWidgetGtk2Module +{5551a1e0-5a66-11d3-806a-00600811a9c3},,application/x-mozilla-static,,application +{50e95301-17a8-11d4-9f7e-dd530d5f057c},,application/x-mozilla-static,,nsComposerModule +{6c3c274b-4cbf-4bb5-a635-05ad2cbb6535},,application/x-mozilla-static,,docshell_provider +{25029490-f132-11d2-9588-00805f369f95},,application/x-mozilla-static,,necko +{30dcd313-73e1-447d-8339-37744952154e},,application/x-mozilla-static,,nsUConvModule +{e638d760-8687-11d2-b530-000000000001},,application/x-mozilla-static,,nsRDFModule +{fc886801-e768-11d4-9885-00c04fa0cf4b},,application/x-mozilla-static,,nsLayoutModule +{ac2bb8fe-eeeb-4572-b40f-be03932b56e0},,application/x-mozilla-static,,nsImageLib2Module +{4ea60761-31d6-491d-9e34-4b53a26c416c},,application/x-mozilla-static,,NSS +{aa40253b-4c42-4056-8132-37bcd07862fd},,application/x-mozilla-static,,nsLayoutModule +{baa34652-f1f1-4185-b224-244ee82a413a},,application/x-mozilla-static,,nsLayoutModule +{fbc81170-1f69-11d3-9344-00104ba0fd40},@mozilla.org/network/protocol;1?name=file,application/x-mozilla-static,nsFileProtocolHandler,necko +{a0d6ad32-1dd1-11b2-aa55-a40187b54036},,application/x-mozilla-static,,necko +{984e3259-9266-49cf-b605-60b022a00756},,application/x-mozilla-static,,nsPlacesModule +{ba6151ab-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7584ce90-5b25-11d3-a175-0050041caf44},,application/x-mozilla-static,,necko +{0a5cd734-eb65-4d14-88a0-9f0bb2aba206},,application/x-mozilla-static,,nsRDFModule +{749e62f4-60ae-4569-a8a2-de78b649660e},,text/javascript,,rel:nsLoginManagerPrompter.js +{9a28ffa7-e6ef-4b52-a127-6ad951de8e9b},,application/x-mozilla-native,,rel:libbrowsercomps.so +{77da64d3-7458-4920-9491-86cc9914f904},,text/javascript,,rel:NetworkGeolocationProvider.js +{2d96b3df-c051-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsWidgetGtk2Module +{a6cf9115-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsGfxModule +{5c337258-a580-472e-8615-f277ddc5bb06},,application/x-mozilla-static,,nsWidgetGtk2Module +{0e3afd3d-eb60-4c2b-963b-56d7c439f124},,application/x-mozilla-static,,nsLayoutModule +{8eaaf524-7d6d-4f7d-ae8b-9277b324008d},,text/javascript,,rel:nsAddonRepository.js +{6394eeac-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{36fa00c2-1dd2-11b2-be07-d16eeb4c50ed},,application/x-mozilla-static,,nsImageLib2Module +{275d800e-3f60-4896-adb7-d7f390ce0e42},@mozilla.org/network/url-parser;1?auth=yes,application/x-mozilla-static,nsAuthURLParser,necko +{a59da931-4091-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{0659cb83-faad-11d2-8e19-b206620a657c},,application/x-mozilla-static,,appshell +{f3294b1c-89f4-46f8-98a0-44e1eae92518},,text/javascript,,rel:nsExtensionManager.js +{2d524fd1-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{20557898-1dd2-11b2-8f65-9c462ee2bc95},,application/x-mozilla-static,,nsImageLib2Module +{2d96b3d1-c051-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsWidgetGtk2Module +{13111d00-ce81-11d6-8082-ecf3665af67c},,application/x-mozilla-static,,nsLayoutModule +{bc26ff01-f2bd-11d4-a73c-e5a4b5a8bdfc},,application/x-mozilla-static,,nsComposerModule +{a41661d5-1417-11d5-9882-00c04fa02f40},,application/x-mozilla-static,,docshell_provider +{ba6151b8-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{b57f97c2-0d70-11d3-8aae-00600811a836},,application/x-mozilla-static,,nsUConvModule +{c87a37fc-8109-4ce2-a322-8cdec925379f},,application/x-mozilla-static,,nsLayoutModule +{9416bfb2-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{e7ba1480-1dea-11d3-830f-00104bed045e},,application/x-mozilla-static,,nsLayoutModule +{6803cacb-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{f68578eb-6ec2-4169-ae19-8c6243f0abe1},,text/javascript,,rel:nsHelperAppDlg.js +{d92d57c5-ba1d-11d2-af0c-0060089fe59b},,application/x-mozilla-static,,nsI18nModule +{e036c738-1dd1-11b2-9392-9d94aa74b0c5},,application/x-mozilla-static,,nsAutoConfigModule +{8b5314bb-db01-11d2-96ce-0060b0fb9956},,application/x-mozilla-static,,nsWidgetGtk2Module +{e7509b46-2eb2-410a-9d7c-c3ce73284d01},,application/x-mozilla-static,,nsLayoutModule +{d673255d-1184-400a-b0b5-ee9d1295bd85},,application/x-mozilla-static,,nsUConvModule +{6394eeb9-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc},,application/x-mozilla-static,,nsLayoutModule +{a33982d3-1adf-4162-9941-f734bc45e4ed},,application/x-mozilla-static,,nsComposerModule +{7b8556aa-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{bd6390c8-fbea-11d4-98f6-001083010e9b},,application/x-mozilla-static,,docshell_provider +{c375fa80-150f-11d6-a618-0010a401eb10},,application/x-mozilla-static,,necko +{660d8ca3-f763-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{d750a964-2d14-484c-b3aa-8ed7823b5c7b},,application/x-mozilla-static,,nsLayoutModule +{f57899d0-4e2c-4ac6-9e29-50c736103b0c},,text/javascript,,rel:nsSetDefaultBrowser.js +{786e0a0e-e035-4600-8ee0-365a63a80b80},,application/x-mozilla-static,,nsToolkitCompsModule +{b0ff4572-dae4-4bef-a092-83c1b88f6be9},@mozilla.org/network/dns-service;1,application/x-mozilla-static,nsDNSService,necko +{bbc23860-2553-479d-8b78-94d9038334f7},,text/javascript,,rel:nsTaggingService.js +{064d9cee-1dd2-11b2-83e3-d25ab0193c26},,application/x-mozilla-static,,nsPrefModule +{6394eea4-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6ee5301a-3981-49bd-85f8-1a2cc228cf3e},,application/x-mozilla-static,,nsUniversalCharDetModule +{9416bfbf-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{2bf64765-997f-450d-af96-3028d1a902b0},,application/x-mozilla-static,,nsI18nModule +{9c8f9601-801a-11d2-98ba-00805f297d89},,application/x-mozilla-static,,nsTransactionManagerModule +{6c392c62-1ab1-4de7-bfc6-ed4f9fc7749a},,application/x-mozilla-static,,nsLayoutModule +{2cd0c310-e127-44d0-88fc-4435c9ab4d4b},,text/javascript,,rel:jsconsole-clhandler.js +{b7b2ccec-7912-4ea6-a548-b038447004bd},,application/x-mozilla-static,,nsToolkitCompsModule +{06893e69-71d8-4b23-81eb-80314daf3e66},,application/x-mozilla-native,,rel:libbrowsercomps.so +{d899a152-9412-46b2-b651-2e71c5c2f05f},,application/x-mozilla-static,,nsLayoutModule +{217d014a-1dd2-11b2-999c-b0c4df79b324},,application/x-mozilla-static,,NSS +{80d7e247-d4b8-45d7-bb59-6f1dd56f384c},,application/x-mozilla-static,,nsLayoutModule +{ba6151b0-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{df71c6f0-ec53-11d2-bdca-000064657374},,application/x-mozilla-static,,nsRDFModule +{c2be6dc0-ef1e-4abd-86a2-4f864ddc57f6},,application/x-mozilla-static,,nsToolkitCompsModule +{792a7e82-06a0-437c-af63-b2d12e808acc},,text/javascript,,rel:WebContentConverter.js +{495eca45-0a5c-11d4-a135-005004832142},,application/x-mozilla-static,,nsUConvModule +{78c61626-4d1f-4843-9364-4652d98ff6e1},,application/x-mozilla-static,,nsImageLib2Module +{6356aa16-7916-4215-a825-cbc2692ca87a},,application/x-mozilla-static,,application +{e11a6080-4daa-11d2-b328-00805f8a3859},,application/x-mozilla-static,,nsLayoutModule +{7e6e57c0-e2f2-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{ea06d4e3-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{5d0cfa97-69dd-4e5e-ac84-f253162e8f9a},,text/javascript,,rel:FeedProcessor.js +{5871a422-1dd2-11b2-ab3f-e2e56be5da9c},,application/x-mozilla-static,,nsImageLib2Module +{15629ada-a41c-4a09-961f-6553cd60b1a2},,application/x-mozilla-static,,necko +{e197cc01-cfe1-11d4-8eb0-87ae406dfd3f},,application/x-mozilla-static,,nsLayoutModule +{2ea2e7d0-4095-11d3-9144-006008a6edf6},,application/x-mozilla-static,,nsI18nModule +{dd156d62-d26f-4441-9cdb-e8f09107c273},,application/x-mozilla-static,,nsSecurityManagerModule +{6394eeb1-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{c272fee0-c7e9-11d3-8cda-0060b0fc14a3},@mozilla.org/network/file-output-stream;1,application/x-mozilla-static,nsFileOutputStream,necko +{96ec4163-efc8-407a-8735-007fb26be4e8},,application/x-mozilla-static,,nsAuthModule +{e38e53b9-5bb0-456a-b553-579370cb1567},,application/x-mozilla-static,,xpconnect +{a6cf90e3-15b3-11d2-932e-00805f8add32},,application/x-mozilla-static,,nsLayoutModule +{d164e770-4157-11d4-9a42-000064657374},,application/x-mozilla-static,,nsLayoutModule +{2d524fd6-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{a277189c-1dd1-11b2-a8c9-e4e8bfb1338e},,application/x-mozilla-static,,NSS +{301dea42-6850-4cda-8945-81f7dbc2186b},,application/x-mozilla-static,,necko +{b322a5c0-a419-484e-96ba-d7182163899f},,text/javascript,,rel:nsUpdateTimerManager.js +{9c47c121-1c6e-4d8f-b904-3ac968116e88},,application/x-mozilla-static,,docshell_provider +{8b449142-1eab-4bfa-9830-fab6ebb09774},,application/x-mozilla-static,,nsLayoutModule +{6bd13476-1dd2-11b2-bbef-f0ccb5fa64b6},@mozilla.org/moz/jsloader;1,application/x-mozilla-static,JS component loader,xpconnect +{c8e518c1-47ae-11d3-91cd-00105aa3f7dc},,application/x-mozilla-static,,nsI18nModule +{2fd6b7f6-eb8c-4f32-ad26-113f2c02d0fe},,application/x-mozilla-static,,JavaScript_Debugger +{ff9fbcd7-9517-4334-b97a-ceed78909974},,application/x-mozilla-static,,NSS +{510a86bb-6019-4ed1-bb4f-965cffd23ece},,application/x-mozilla-static,,necko +{b084a2ce-1dd1-11b2-bf10-8324f8e065cc},,application/x-mozilla-static,,NSS +{3d262d00-8b5a-11d2-8eb0-00805f29f370},,application/x-mozilla-static,,nsLayoutModule +{dca61eb5-c7cd-4df1-b0fb-d0722baba251},,text/javascript,,rel:nsLivemarkService.js +{ea06d4e4-2b3d-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUniversalCharDetModule +{660a3226-915c-4ffb-bb20-8985a632df05},,application/x-mozilla-static,,NSS +{2ec62893-3b35-48fa-ab1d-5e68a9f45f08},,application/x-mozilla-static,,necko +{ce002b28-92b7-4701-8621-cc925866fb87},,application/x-mozilla-static,,nsCookieModule +{7ef52eaf-b7e1-462b-87e2-5d1dbaca9048},,application/x-mozilla-static,,mozSpellCheckerModule +{c95f1831-c376-11d1-b721-00600891d8c9},,application/x-mozilla-static,,nsLayoutModule +{cf3a0e06-1dd1-11b2-a904-ac1d6da77a02},,application/x-mozilla-static,,necko +{9b6dc177-a2e4-49e1-9c98-0a8384de7f6c},,application/x-mozilla-native,,rel:libnkgnomevfs.so +{56c778e4-1bee-45f3-a689-886692a97fe7},,application/x-mozilla-static,,mozSpellCheckerModule +{ec06f3fc-70db-4ecd-94e0-a6e91ca44d8a},,application/x-mozilla-static,,docshell_provider +{7bd05c78-6a26-11d7-b16f-0003938a9d96},,application/x-mozilla-static,,nsLayoutModule +{6394eebe-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{7b8556af-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{379c2777-ec77-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{de401c37-9a7f-4278-a6f8-3de2833989ef},,application/x-mozilla-static,,nsAccessibilityModule +{4ec832da-6ae7-4185-807b-daddcb5da37a},,application/x-mozilla-static,,nsLayoutModule +{f0acde16-1dd1-11b2-9e35-f5786fff5a66},,application/x-mozilla-static,,docshell_provider +{56e2ada8-4631-11d4-ba11-001083023c1e},,application/x-mozilla-static,,nsLayoutModule +{f34ff792-722e-4490-b195-47d242edca1c},,application/x-mozilla-native,,rel:libbrowsercomps.so +{61ba33c0-3031-11d3-8cd0-0060b0fc14a3},,application/x-mozilla-static,,nsChromeModule +{ad78bbf0-e261-482b-32b3-78a7b2afc8f7},,application/x-mozilla-static,,nsLayoutModule +{bbef8185-c628-4cc1-b53e-e61e74c2451a},,application/x-mozilla-static,,necko +{9416bfc1-1f93-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{aa13e4a0-a5ac-11d2-9119-006008a6edf6},,application/x-mozilla-static,,nsI18nModule +{7c657d17-ec5e-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{6394eea9-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{66354bc9-7ed1-4692-ae1d-8da97d6b205e},,text/javascript,,rel:nsBlocklistService.js +{171e72db-0f8a-412a-8461-e4c927a3a2ac},,application/x-mozilla-static,,nsComposerModule +{ef565d0a-ab9a-4a13-9160-0644cdfd859a},,application/x-mozilla-static,,nsCookieModule +{735959a1-af01-447e-b02d-56e968fa52b4},,application/x-mozilla-static,,NSS +{cb9e0de8-3598-4ed7-857b-827f011ad5d8},,text/javascript,,rel:nsLoginManager.js +{5e8d4751-1852-434b-a992-2c6d2a25fa46},,application/x-mozilla-static,,nsPlacesModule +{ecd55a01-2780-11d5-a73c-ca641a6813bc},,application/x-mozilla-static,,embedcomponents +{2002f782-3960-11d3-b3c3-00805f8a6670},,application/x-mozilla-static,,nsChardetModule +{c11c21b2-71c9-4f87-a0f8-5e13f50495fd},,text/javascript,,rel:nsFormAutoComplete.js +{8227f019-afc7-461e-b030-9f185d7a0e29},,application/x-mozilla-static,,mozSpellCheckerModule +{1d40026b-4c44-4f6f-b158-26bb5e9c65e9},,application/x-mozilla-static,,nsLayoutModule +{e28ab250-d66d-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{ba6151b5-1dfa-11d3-b3bf-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{4f76e100-d71c-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{88cecbb7-6c63-4b3b-8cd4-84f3b8228c69},,application/x-mozilla-static,,nsPlacesModule +{d85a17c1-aa7c-11d2-9b8c-00805f8a16d9},@mozilla.org/intl/stringbundle;1,application/x-mozilla-static,String Bundle,nsI18nModule +{a578e0a2-f76b-11d2-8aad-00600811a836},,application/x-mozilla-static,,nsUConvModule +{f7c9f5f4-4451-41c3-a28a-5ba2447fbace},,application/x-mozilla-static,,necko +{7b8556b0-ec79-11d2-8aac-00600811a836},,application/x-mozilla-static,,nsUConvModule +{1147d32c-215b-4014-b180-07fe7aedf915},,application/x-mozilla-static,,nsLayoutModule +{905f80f1-8a7b-11d2-918c-0080c8e44db5},,application/x-mozilla-static,,nsLayoutModule +{6803cac8-1e3b-11d5-a145-005004832142},,application/x-mozilla-static,,nsUConvModule +{758e4f20-e2f2-11d3-b32f-004005a7a7e4},,application/x-mozilla-static,,nsUCvMathModule +{6394eea1-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{6049b261-c1e6-11d1-a827-0040959a28c9},,application/x-mozilla-static,,nsGfxModule +{6394eeb6-fc3d-11d2-b3b8-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{bd57cee8-1dd1-11b2-9fe7-95cf4709aea3},,application/x-mozilla-static,,nsWidgetGtk2Module +{9c0ff6f4-deda-40e5-806c-b6cc449c21ce},,application/x-mozilla-static,,nsUConvModule +{49b38f12-6193-11d3-b3c5-00805f8a6670},,application/x-mozilla-static,,nsUConvModule +{2d524fdb-ae74-11d3-abf7-0004aceefa51},,application/x-mozilla-static,,nsUConvModule +{7f915b01-98fc-11d4-8eb0-a803f80ff1bc},,application/x-mozilla-static,,nsLayoutModule +{430d416c-a722-4ad1-be98-d9a445f85e3f},,application/x-mozilla-static,,ZipWriterModule +{245abae2-b947-4ded-a46d-9829d3cca462},,application/x-mozilla-static,,nsJarModule +{cb9abbae-66b6-4609-8594-5c4ff300888e},,application/x-mozilla-static,,necko +{82776710-5690-11d3-be36-00104bde6048},,application/x-mozilla-static,,application +{2c3837af-8b85-4a68-b0d8-0aed88985b32},,application/x-mozilla-static,,NSS +{23bcc750-dc20-460b-b2d4-74d8f58d3615},,application/x-mozilla-static,,CommandLineModule +{cc75499a-1dd1-11b2-8a82-ca410ac907b8},,application/x-mozilla-static,,BOOT +{dbfcbe4a-10f7-4d6f-a481-68e6d6b71d21},,application/x-mozilla-static,,NSS +{c744ca3d-840b-460a-8d70-7ce63c51c958},,application/x-mozilla-static,,nsWindowDataSourceModule +{be65e2b7-fe46-4e0f-88e0-4b385db4d68a},,application/x-mozilla-static,,NSS +{dca9d7c3-7b6a-4490-ad6d-2699a8d683cd},,application/x-mozilla-static,,nsLayoutModule +{dc26e0e0-ca94-11d1-a9a4-00805f8a7ac4},,application/x-mozilla-static,,nsPrefModule +{b7f44954-11d1-11b2-8c2e-c2feab4186bc},,application/x-mozilla-static,,nsLayoutModule +{9f1800ab-f428-4207-b40c-e832e77b01fc},,application/x-mozilla-static,,nsWidgetGtk2Module +{0320e073-79c7-4dae-8055-81bed8b8db96},,application/x-mozilla-static,,nsJarModule +{93ad72a6-02cd-4716-9626-d47d5ec275ec},,application/x-mozilla-static,,nsLayoutModule + +[CONTRACTIDS] +@mozilla.org/intl/unicode/encoder;1?charset=Big5,{efc323e2-ec62-11d2-8aac-00600811a836} +@mozilla.org/gfx/region/nsThebes;1,{e12752f0-ee9a-11d1-a82a-0040959a28c9} +@mozilla.org/image/tools;1,{fd9a9e8a-a77b-496a-b7bb-263df9715149} +@mozilla.org/network/effective-tld-service;1,{cb9abbae-66b6-4609-8594-5c4ff300888e} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-greek,{7b8556b1-ec79-11d2-8aac-00600811a836} +@mozilla.org/extensions/addon-repository;1,{8eaaf524-7d6d-4f7d-ae8b-9277b324008d} +@mozilla.org/inspector/dom-utils;1,{40b22006-5dd5-42f2-bfe7-7dbf0757ab8b} +@mozilla.org/xtf/xml-contentbuilder;1,{e09af32d-2a54-4d76-9ef0-3070e83f8be7} +@mozilla.org/intl/unicharcategory;1,{748a1132-671a-409a-8d1d-f1cdf6b3a6b4} +@mozilla.org/intl/unicode/decoder;1?charset=x-windows-949,{9416bfbf-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-6,{660d8ca8-f763-11d2-8aad-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-32,{30dcd313-73e1-447d-8339-37744952154e} +@mozilla.org/content/post-content-iterator;1,{a6cf90e3-15b3-11d2-932e-00805f8add32} +@mozilla.org/intl/unicode/encoder;1?charset=x-t1-cmmi,{bd1326a6-5a14-48de-97cc-95b5195f4fb9} +@mozilla.org/network/mime-hdrparam;1,{1f4dbcf7-245c-4c8c-943d-8a1da0495e8a} +@mozilla.org/network/protocol/about;1?what=config,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/network/sync-stream-listener;1,{439400d3-6f23-43db-8b06-8aafe1869bd8} +@mozilla.org/intl/unicode/decoder;1?charset=x-viet-tcvn5712,{6394eead-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/download-manager-ui;1,{7dfdf0d1-aff6-4a34-bad1-d0fe74601642} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-arabic,{6803cac7-1e3b-11d5-a145-005004832142} +@mozilla.org/url-classifier/streamupdater;1,{c2be6dc0-ef1e-4abd-86a2-4f864ddc57f6} +@mozilla.org/xmlextras/domparser;1,{3a8a3a50-512c-11d4-9a54-000064657374} +@mozilla.org/streamconv;1?from=x-compress&to=uncompressed,{66230b2b-17fa-4bd3-abf4-07986151022d} +@mozilla.org/network/protocol-proxy-service;1,{e9b301c0-e0e4-11d3-a1a8-0050041caf44} +@mozilla.org/storage/service;1,{bbbb1d61-438f-4436-92ed-8308e5830fb0} +@mozilla.org/image/decoder;2?type=image/icon,{ffc08380-256c-11d5-9905-001083010e9b} +@mozilla.org/widget/clipboardhelper;1,{77221d5a-1dd2-11b2-8c69-c710f15d2ed5} +@mozilla.org/network/server-socket;1,{2ec62893-3b35-48fa-ab1d-5e68a9f45f08} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-14,{6394eeb1-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-turkish,{7b8556a4-ec79-11d2-8aac-00600811a836} +@mozilla.org/uriloader/web-handler-app;1,{8b1ae382-51a9-4972-b930-56977a57919d} +@mozilla.org/intl/saveascharset;1,{0cd233e0-7a86-11d3-915c-006008a6edf6} +@mozilla.org/network/http-authenticator;1?scheme=basic,{fca3766a-434a-4ae7-83cf-0909e18a093a} +@mozilla.org/sidebar;1,{22117140-9c6e-11d3-aaf1-00805f8a4905} +@mozilla.org/streamconv;1?from=text/plain&to=text/html,{9ef9fa14-1dd1-11b2-9d65-d72d6d1f025e} +@mozilla.org/webnavigation-info;1,{f30bc0a2-958b-4287-bf62-ce38ba0c811e} +@mozilla.org/intl/charsetdetect;1?type=ukprob,{2002f782-3960-11d3-b3c3-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1251,{a578e0a1-f76b-11d2-8aad-00600811a836} +@mozilla.org/storage/statement-wrapper;1,{dab3a846-3a59-4fc2-9745-c6ff48776f00} +@mozilla.org/layout/contentserializer;1?mimetype=application/xml,{4aef38b7-6364-4e23-a5e7-12f837fbbd9c} +@mozilla.org/system-proxy-settings;1,{0fa3158c-d5a7-43de-9181-a285e74cf1d4} +@mozilla.org/gfx/renderingcontext;1,{6049b261-c1e6-11d1-a827-0040959a28c9} +@mozilla.org/image/decoder;2?type=image/jpg,{5871a422-1dd2-11b2-ab3f-e2e56be5da9c} +@mozilla.org/security/crlmanager;1,{5b256c10-22d8-4109-af92-1253035e9fcb} +@mozilla.org/layout/contentserializer;1?mimetype=image/svg+xml,{4aef38b7-6364-4e23-a5e7-12f837fbbd9c} +@mozilla.org/network/mime-input-stream;1,{58a1c31c-1dd2-11b2-a3f6-d36949d48268} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-8,{5534ddc0-dd96-11d2-8aac-00600811a836} +@mozilla.org/dom/storage;1,{8b449142-1eab-4bfa-9830-fab6ebb09774} +@mozilla.org/embedding/browser/nsCommandHandler;1,{3a449110-66fd-11d4-9528-0020183bf181} +@mozilla.org/intl/unicode/encoder;1?charset=IBM850,{2d524fd6-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1254,{7b8556ae-ec79-11d2-8aac-00600811a836} +@mozilla.org/sound;1,{b148eed2-236d-11d3-b35c-00a0cc3c1cde} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-devanagari,{6803cac5-1e3b-11d5-a145-005004832142} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-6,{660d8ca3-f763-11d2-8aad-00600811a836} +@mozilla.org/xpinstall/install-manager;1,{6a4d4c1e-a74a-4320-8124-16233a0183d6} +@mozilla.org/passwordmanager/authpromptfactory;1,{749e62f4-60ae-4569-a8a2-de78b649660e} +@mozilla.org/extensions/blocklist;1,{66354bc9-7ed1-4692-ae1d-8da97d6b205e} +@mozilla.org/widget/bidikeyboard;1,{9f1800ab-f428-4207-b40c-e832e77b01fc} +@mozilla.org/permissions/contentblocker;1,{4ca6b67b-5cc7-4e71-a98a-97af1c134862} +@mozilla.org/appshell/component/browser-status-filter;1,{6356aa16-7916-4215-a825-cbc2692ca87a} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-2022-CN,{ba615199-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/security/nsASN1Tree;1,{4bfaa9f0-1dd2-11b2-afae-a82cbaa0b606} +@mozilla.org/intl/texttransform;1?type=hankakutozenkaku,{8f666a11-04a0-11d3-b3b9-00805f8a6670} +@mozilla.org/intl/charsetdetect;1?type=ruprob,{2002f781-3960-11d3-b3c3-00805f8a6670} +@mozilla.org/uriloader/content-handler;1?type=text/css,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/widget/native-key-bindings;1?type=input,{5c337258-a580-472e-8615-f277ddc5bb06} +@mozilla.org/streamconv;1?from=text/gopher-dir&to=application/http-index-format,{ea617873-3b73-4efd-a2c4-fc39bfab809d} +@mozilla.org/editor/editorcontroller;1,{26fb965c-9de6-11d3-bccc-0060b0fc76bd} +@mozilla.org/layout/documentEncoder;1?type=application/xml,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/image/decoder;2?type=image/gif,{797bec5a-1dd2-11b2-a7f8-ca397e0179c4} +@mozilla.org/intl/texttosuburi;1,{8b042e22-6f87-11d3-b3c8-00805f8a6670} +@mozilla.org/network/http-activity-distributor;1,{15629ada-a41c-4a09-961f-6553cd60b1a2} +@mozilla.org/network/protocol/about;1?what=buildconfig,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/widget/htmlformatconverter;1,{948a0023-e3a7-11d2-96cf-0060b0fb9956} +@mozilla.org/intl/unicode/encoder;1?charset=Shift_JIS,{e28ab250-d66d-11d2-8aac-00600811a836} +@mozilla.org/nsCertificateDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/streamconv;1?from=application/http-index-format&to=text/html,{cf0f71fd-fafd-4e2b-9fdc-134d972e16e2} +@mozilla.org/network/stream-transport-service;1,{0885d4f8-f7b8-4cda-902e-94ba38bc256e} +@mozilla.org/js/xpc/RuntimeService;1,{b5e65b52-1dd1-11b2-ae8f-f0928ed88482} +@mozilla.org/network/binary-detector;1,{a2027ec6-ba0d-4c72-805d-148233f5f33c} +@mozilla.org/intl/charsetalias;1,{98d41c21-ccf3-11d2-b3b1-00805f8a6670} +@mozilla.org/browser/favicon-service;1,{984e3259-9266-49cf-b605-60b022a00756} +@mozilla.org/globalprefsecuritycheck;1,{7ee2a4c0-4b93-17d3-ba18-0060b0f199a2} +@mozilla.org/js/xpc/Exception;1,{5632bf70-51ec-11d3-9896-006008962422} +@mozilla.org/feed-person;1,{95c963b7-20b2-11db-92f6-001422106990} +@mozilla.org/xul/xul-popup-manager;1,{14632191-ac21-4bdf-83e7-2363ad17e838} +@mozilla.org/content/plugin/document-loader-factory;1,{0ddf4df8-4dbb-4133-8b79-9afb966514f5} +@mozilla.org/network/request-observer-proxy;1,{51fa28c7-74c0-4b85-9c46-d03faa7b696b} +@mozilla.org/browser/clh;1,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/embedcomp/controller-command-group;1,{ecd55a01-2780-11d5-a73c-ca641a6813bc} +@mozilla.org/uriloader/content-handler;1?type=text/plain,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/network/socket;2?type=starttls,{b9507aec-1dd1-11b2-8cd5-c48ee0c50307} +@mozilla.org/uriloader/external-helper-app-service;1,{a7f800e0-4306-11d4-98d0-001083010e9b} +@mozilla.org/scriptsecuritymanager;1,{7ee2a4c0-4b93-17d3-ba18-0060b0f199a2} +@mozilla.org/browser/browserglue;1,{eab9012e-5f74-4cbc-b2b5-a590235513cc} +@mozilla.org/network/protocol;1?name=ftp,{25029490-f132-11d2-9588-00805f369f95} +@mozilla.org/js/xpc/XPConnect;1,{cb6593e0-f9b2-11d2-bdd6-000064657374} +@mozilla.org/intl/unicode/encoder;1?charset=x-mathematica3,{830b5f80-e2f2-11d3-b32f-004005a7a7e4} +@mozilla.org/intl/unicode/decoder;1?charset=Big5-HKSCS,{ba6151bb-ec62-11d2-8aac-00600811a836} +@mozilla.org/security/psmdownload;1,{c94f4a30-64d7-11d4-9960-00b0d02354a0} +@mozilla.org/image/container;2,{376ff2c1-9bf6-418a-b143-3340c00112f7} +@mozilla.org/embedcomp/find;1,{57cf9383-3405-11d5-be5b-aa20fa2cf37c} +@mozilla.org/autocomplete/controller;1,{f6d5ebbd-34f4-487d-9d10-3d34123e3eb9} +@mozilla.org/network/unichar-stream-loader;1,{9445791f-fa4c-4669-b174-df5032bb67b3} +@mozilla.org/nsTokenDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/intl/scriptabledateformat;1,{2ea2e7d0-4095-11d3-9144-006008a6edf6} +@mozilla.org/network/application-cache-service;1,{02bf7a2a-39d8-4a23-a50c-2cbb085ab7a5} +@mozilla.org/network/http-authenticator;1?scheme=ntlm,{bbef8185-c628-4cc1-b53e-e61e74c2451a} +@mozilla.org/intl/unicode/encoder;1?charset=gb18030,{a59da932-4091-11d5-a145-005004832142} +@mozilla.org/geolocation/provider;1,{77da64d3-7458-4920-9491-86cc9914f904} +@mozilla.org/intl/charsetdetect;1?type=ko_parallel_state_machine,{ea06d4e1-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/inspector/search;1?type=cssvalue,{4d977f60-fbe7-4583-8cb7-f5ed882293ef} +@mozilla.org/network/socket;2?type=socks,{8dbe7246-1dd2-11b2-9b8f-b9a849e4403a} +@mozilla.org/intl/platformcharset;1,{84b0f182-c6c7-11d2-b3b0-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-arabic,{6803cac6-1e3b-11d5-a145-005004832142} +@mozilla.org/intl/charsetdetect;1?type=cjk_parallel_state_machine,{fcacef24-2b40-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=KOI8-U,{6394eea6-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=x-t1-cmr,{d5eb483c-67c0-4286-a4a6-330e58a82300} +@mozilla.org/browser/sessionstore;1,{5280606b-2510-4fe0-97ef-9b5a22eafe6b} +@mozilla.org/pref-localizedstring;1,{064d9cee-1dd2-11b2-83e3-d25ab0193c26} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-6-E,{495eca45-0a5c-11d4-a135-005004832142} +@mozilla.org/security/nsscertcache;1,{3f429a14-dffe-417d-8cb8-fdf09bacd09e} +@mozilla.org/libjar/zip-reader-cache;1,{1b117e16-0cad-11d4-986e-00c04fa0cf4a} +@mozilla.org/url-classifier/utils;1,{b7b2ccec-7912-4ea6-a548-b038447004bd} +@mozilla.org/network/protocol/about;1?what=home,{7a2a7a56-827f-4b38-bdac-31aa7ec2971d} +@mozilla.org/intl/unicode/encoder;1?charset=windows-936,{9416bfc1-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/editor/txtsrvfilter;1,{171e72db-0f8a-412a-8461-e4c927a3a2ac} +@joehewitt.com/firebug-http-observer;1,{2d92593e-14d0-48ce-b260-a9881bbf9c8b} +@mozilla.org/nsDOMCryptoDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/intl/unicode/decoder;1?charset=armscii-8,{6394eeac-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/jsctypes;1,{0c797702-1c60-4051-9dd7-4d7405605642} +@mozilla.org/intl/unicode/encoder;1?charset=windows-874,{6394eeb4-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/protocol;1?name=resource,{e64f152a-9f07-11d3-8cda-0060b0fc14a3} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-3,{660d8ca5-f763-11d2-8aad-00600811a836} +@mozilla.org/accelerometer;1,{ecba5203-77da-465a-865e-78b7af10d8f7} +@mozilla.org/network/url-parser;1?auth=yes,{275d800e-3f60-4896-adb7-d7f390ce0e42} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-8-I,{495eca48-0a5c-11d4-a135-005004832142} +@mozilla.org/embedcomp/cookieprompt-service;1,{ce002b28-92b7-4701-8621-cc925866fb87} +@mozilla.org/intl/unicode/encoder;1?charset=x-zapf-dingbats,{21dd6a03-413c-11d3-b3c3-00805f8a6670} +@mozilla.org/network/idn-service;1,{62b778a6-bce3-456b-8c31-2865fbb68c91} +@mozilla.org/network/input-stream-channel;1,{6ddb050c-0d04-11d4-986e-00c04fa0cf4a} +@mozilla.org/microsummary/service;1,{460a9792-b154-4f26-a922-0f653e2c8f91} +@mozilla.org/toolkit/app-startup;1,{7dd4d320-c84b-4624-8d45-7bb9b2356977} +@mozilla.org/url-classifier/listmanager;1,{ca168834-cc00-48f9-b83c-fd018e58cae3} +@mozilla.org/network/auth-module;1?name=ntlm,{a4e5888f-4fe4-4632-8e7e-745196ea7c70} +@mozilla.org/intl/xmlencoding;1,{12bb8f16-2389-11d3-b3bf-00805f8a6670} +@mozilla.org/network/socket;2?type=udp,{320706d2-2e81-42c6-89c3-8d83b17d3fb4} +@mozilla.org/intl/unicode/encoder;1?charset=x-johab,{d9b1f97e-cfa0-80b6-fb92-9972e48e3dcc} +@mozilla.org/spellchecker/personaldictionary;1,{7ef52eaf-b7e1-462b-87e2-5d1dbaca9048} +@mozilla.org/security/hmac;1,{a496d0a2-dff7-4e23-bd65-1ca742fa178a} +@mozilla.org/browser/global-history;1,{a772eee4-0464-405d-a329-a29dfda3791a} +@mozilla.org/widget/idleservice;1,{6987230e-0098-4e78-bc5f-1493ee7519fa} +@mozilla.org/xpinstall/installtrigger;1,{18c2f98d-b09f-11d2-bcde-00805f0e1353} +@mozilla.org/layout/documentEncoder;1?type=application/xhtml+xml,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/network/protocol;1?name=http,{4f47e42e-4d23-4dd3-bfda-eb29255e9ea3} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1252,{7c657d15-ec5e-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-32,{49b38f14-6193-11d3-b3c5-00805f8a6670} +@mozilla.org/intl/semanticunitscanner;1,{adf42751-1cef-4ad2-aa8e-bcb849d8d31f} +@mozilla.org/rdf/datasource;1?name=in-memory-datasource,{bfd0526d-834c-11d2-8eac-00805f29f370} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-16LE,{ba6151b7-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/streamconv;1?from=compress&to=uncompressed,{66230b2b-17fa-4bd3-abf4-07986151022d} +@mozilla.org/intl/unicode/decoder;1?charset=us-ascii,{ba6151b9-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/network/stream-loader;1,{5ba6d920-d4e9-11d3-a1a5-0050041caf44} +@mozilla.org/content/canvas-rendering-context;1?id=2d,{a35d1cd4-c505-4d2d-a0f9-aef00b7ce5a5} +@mozilla.org/layout/contentserializer;1?mimetype=text/html,{9d3f70da-86e9-11d4-95ec-00b0d03e37b7} +@mozilla.org/network/socket;2?type=ssl,{217d014a-1dd2-11b2-999c-b0c4df79b324} +@mozilla.org/intl/unicode/encoder;1?charset=x-windows-949,{9416bfbe-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/security/hash;1,{36a1d3b3-d886-4317-96ff-87b0005cfef7} +@mozilla.org/network/auth-module;1?name=sasl-gssapi,{815e42e0-72cc-480f-934b-148e33c228a6} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1251,{a578e0a3-f76b-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-15,{6394eea2-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-3,{660d8ca0-f763-11d2-8aad-00600811a836} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-32LE,{ba6151b6-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/dom/storagemanager;1,{b88a4712-eb52-4c10-9b85-bf5894b510f0} +@mozilla.org/psm;1,{a277189c-1dd1-11b2-a8c9-e4e8bfb1338e} +@mozilla.org/docloaderservice;1,{057b04d0-0ccf-11d2-beba-00805f8a66dc} +@mozilla.org/streamconv;1?from=application/mac-binhex40&to=*/*,{301dea42-6850-4cda-8945-81f7dbc2186b} +@mozilla.org/network/protocol/about;1?what=cache,{9158c470-86e4-11d4-9be2-00e09872a416} +@mozilla.org/gfx/printsettings-service;1,{841387c8-72e6-484b-9296-bf6eea80d58a} +@mozilla.org/intl/unicode/decoder;1?charset=IBM866,{ba6151a9-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/content/syncload-dom-service;1,{0e4e7d00-f71a-439f-9178-1a71ff11b55f} +@mozilla.org/intl/unicode/encoder;1?charset=us-ascii,{ba6151ba-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=TIS-620,{c5de4da2-d667-42d2-b8c2-efdbcf3302ef} +@mozilla.org/uriloader/content-handler;1?type=text/html,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/security/nsCertTree;1,{4ea60761-31d6-491d-9e34-4b53a26c416c} +@mozilla.org/xul/xul-template-builder;1,{3d262d00-8b5a-11d2-8eb0-00805f29f370} +@mozilla.org/inspector/flasher;1,{9286e71a-621a-4b91-851e-9984c1a2e81a} +@mozilla.org/security/crypto;1,{929d9320-251e-11d4-8a7c-006008c844c3} +@mozilla.org/fuel/application;1,{fe74cf80-aa2d-11db-abbd-0800200c9a66} +@mozilla.org/url-classifier/hashcompleter;1,{786e0a0e-e035-4600-8ee0-365a63a80b80} +@mozilla.org/intl/converter-output-stream;1,{ff8780a5-bbb1-4bc5-8ee7-057e7bc5c925} +@mozilla.org/embeddor.implemented/bookmark-charset-resolver;1,{88cecbb7-6c63-4b3b-8cd4-84f3b8228c69} +@mozilla.org/intl/stringcharsetdetect;1?type=zhcn_parallel_state_machine,{ea06d4e5-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/find/find_service;1,{5060b803-340e-11d5-be5b-b3e063ec6a3c} +@mozilla.org/editor/editingsession;1,{bc26ff01-f2bd-11d4-a73c-e5a4b5a8bdfc} +@mozilla.org/xbl;1,{64f300a1-c88c-11d3-97fb-00400553eef0} +@mozilla.org/uriloader/dbus-handler-app;1,{6c3c274b-4cbf-4bb5-a635-05ad2cbb6535} +@mozilla.org/intl/unicode/encoder;1?charset=GEOSTD8,{6394eebe-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/content-pref/hostname-grouper;1,{8df290ae-dcaa-4c11-98a5-2429a4dc97bb} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-romanian,{6394eeb8-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/util;1,{9ac9e770-18bc-11d3-9337-00104ba0fd40} +@mozilla.org/intl/unicode/encoder;1?charset=x-ttf-cmex,{e91f9440-e076-11d3-b32f-004005a7a7e4} +@mozilla.org/intl/converter-input-stream;1,{2bc2ad62-ad5d-4b7b-a9db-f74ae203c527} +@mozilla.org/network/url-parser;1?auth=maybe,{ff41913b-546a-4bff-9201-dc9b2c032eba} +@mozilla.org/netwerk/global-channel-event-sink;1,{7ee2a4c0-4b93-17d3-ba18-0060b0f199a2} +@mozilla.org/layout/documentEncoder;1?type=image/svg+xml,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-ce,{7b8556b0-ec79-11d2-8aac-00600811a836} +@mozilla.org/permissionmanager;1,{4f6b5e00-0c36-11d5-a535-0010a401eb10} +@mozilla.org/toolkit/crash-reporter;1,{95d89e3e-a169-41a3-8e56-719978e15b12} +@mozilla.org/safebrowsing/application;1,{c64d0bcb-8270-4ca7-a0b3-3380c8ffecb5} +@mozilla.org/network/application-cache-namespace;1,{b00ed78a-04e2-4f74-8e1c-d1af79dfd12f} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-8,{660d8ca9-f763-11d2-8aad-00600811a836} +@mozilla.org/uriloader/content-handler;1?type=image/x-icon,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/accessibleRetrieval;1,{663ca4a8-d219-4000-925d-d8f66406b626} +@mozilla.org/intl/stringcharsetdetect;1?type=cjk_parallel_state_machine,{fcacef22-2b40-11d3-b3bf-00805f8a6670} +@mozilla.org/js/jsd/debugger-service;1,{f1299dc2-1dd1-11b2-a347-ee6b7660e048} +@mozilla.org/docshell;1,{f1eac762-87e9-11d3-af80-00a024ffc08c} +@mozilla.org/image/encoder;2?type=image/png,{38d1592e-b81e-432b-86f8-471878bbfe07} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-cyrillic,{6394eeb9-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/gfx/devicecontextspec;1,{d3f69889-e13a-4321-980c-a39332e21f34} +@mozilla.org/nsGeneratingKeypairInfoDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/cookie/permission;1,{ef565d0a-ab9a-4a13-9160-0644cdfd859a} +@mozilla.org/uriloader/content-handler;1?type=image/bmp,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/intl/unicode/encoder;1?charset=x-mathematica4,{87ed1160-e2f2-11d3-b32f-004005a7a7e4} +@mozilla.org/gnome-gconf-service;1,{d96d5985-a13a-4bdc-9386-ef348d7a97a1} +@mozilla.org/widget/appshell/gtk;1,{2d96b3df-c051-11d1-a827-0040959a28c9} +@mozilla.org/xhtmlparanoidfragmentsink;1,{2d78bbf0-e26c-482b-92b3-78a7b2afc8f7} +@mozilla.org/intl/unicode/decoder;1?charset=GB2312,{379c2774-ec77-11d2-8aac-00600811a836} +@mozilla.org/image/loader;1,{9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7} +@mozilla.org/profile/migrator;1?app=browser&type=seamonkey,{9a28ffa7-e6ef-4b52-a127-6ad951de8e9b} +@mozilla.org/uriloader/psm-external-content-listener;1,{c94f4a30-64d7-11d4-9960-00b0d02354a0} +@mozilla.org/uriloader/content-handler;1?type=image/vnd.microsoft.icon,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/intl/unicode/encoder;1?charset=x-koreanjamo-0,{47433d1d-d9a7-4954-994f-f7a05cf87c2e} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1257,{a578e0a2-f76b-11d2-8aad-00600811a836} +@mozilla.org/widget/window/gtk;1,{2d96b3d0-c051-11d1-a827-0040959a28c9} +@mozilla.org/widget/printdialog-service;1,{06beec76-a183-4d9f-85dd-085f26da565a} +@mozilla.org/login-manager/prompter;1,{8aa66d77-1bbb-45a6-991e-b8f47751c291} +@mozilla.org/network/protocol;1?name=gopher,{44588c1f-2ce8-4ad8-9b16-dfb9d9d513a7} +@mozilla.org/intl/unicode/decoder;1?charset=KOI8-R,{6394eea5-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-romanian,{6394eea8-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/standard-url;1,{de9472d0-8034-11d3-9399-00104ba0fd40} +@mozilla.org/updates/item;1,{f3294b1c-89f4-46f8-98a0-44e1eae92518} +@mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/*,{229fa115-9412-4d32-baf3-2fc407f76fb1} +@mozilla.org/intl/charsetdetect;1?type=zhcn_parallel_state_machine,{ea06d4e2-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/feed-processor;1,{26acb1f0-28fc-43bc-867a-a46aabc85dd4} +@mozilla.org/security/cipherinfo;1,{ec693a6f-0832-49dd-877c-89f6552df5de} +@mozilla.org/network/protocol;1?name=moz-anno,{e8b8bdb7-c96c-4d82-9c6f-2b3c585ec7ea} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-gujarati,{6803cacb-1e3b-11d5-a145-005004832142} +@mozilla.org/xmlextras/xmlserializer;1,{a6cf9124-15b3-11d2-932e-00805f8add32} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-8,{660d8ca4-f763-11d2-8aad-00600811a836} +@mozilla.org/layout/xul-boxobject-container;1,{dca9d7c3-7b6a-4490-ad6d-2699a8d683cd} +@mozilla.org/streamconv;1?from=multipart/mixed&to=*/*,{7584ce90-5b25-11d3-a175-0050041caf44} +@mozilla.org/network/auth-module;1?name=kerb-gss,{dc8e21a0-03e4-11da-8cd6-0800200c9a66} +@mozilla.org/layout/contentserializer;1?mimetype=application/xhtml+xml,{e7c2aaf5-c11a-4954-9dbf-e28edec1fd91} +@mozilla.org/appshell/appShellService;1,{0099907d-123c-4853-a46a-43098b5fb68c} +@mozilla.org/network/protocol/about;1?what=mozilla,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@joehewitt.com/firebug-channel-listener;1,{5aaeb534-fa57-488d-9a73-20c258fc7bdb} +@mozilla.org/js/jsd/app-start-observer;2,{2fd6b7f6-eb8c-4f32-ad26-113f2c02d0fe} +@mozilla.org/network/protocol/about;1?what=plugins,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/intl/unicharutil;1,{cc10c750-9ec3-11d2-b3ae-00805f8a6670} +@mozilla.org/browser/search-service;1,{7319788a-fe93-4db3-9f39-818cf08f4256} +@mozilla.org/intl/unicode/decoder;1?charset=gb18030,{a59da935-4091-11d5-a145-005004832142} +@mozilla.org/browser/feeds/sniffer;1,{06893e69-71d8-4b23-81eb-80314daf3e66} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-greek,{7b8556a3-ec79-11d2-8aac-00600811a836} +@mozilla.org/system-alerts-service;1,{84e11f80-ca55-11dd-ad8b-0800200c9a66} +@mozilla.org/network/protocol/about;1?what=logo,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/intl/unicode/encoder;1?charset=T.61-8bit,{ba6151af-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/login-manager/loginInfo;1,{0f2f347c-1e4f-40cc-8efd-792dea70a85e} +@mozilla.org/intl/unicode/decoder;1?charset=T.61-8bit,{ba6151b4-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/embedcomp/appstartup-notifier;1,{1f59b001-02c9-11d5-ae76-cc92f7db9e03} +@mozilla.org/intl/unicode/encoder;1?charset=IBM855,{2d524fd8-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-ce,{7b8556a2-ec79-11d2-8aac-00600811a836} +@mozilla.org/rdf/datasource;1?name=composite-datasource,{e638d761-8687-11d2-b530-000000000000} +@mozilla.org/satchel/form-history;1,{a2059c0e-5a58-4c55-ab7c-26f0557546ef} +@mozilla.org/nsClientAuthDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/intl/datetimeformat;1,{0704e7c0-a758-11d2-9119-006008a6edf6} +@mozilla.org/nullprincipal;1,{dd156d62-d26f-4441-9cdb-e8f09107c273} +@mozilla.org/dom/window-controller;1,{7bd05c78-6a26-11d7-b16f-0003938a9d96} +@mozilla.org/inspector/deep-tree-walker;1,{bfcb82c2-5611-4318-90d6-baf4a7864252} +@mozilla.org/intl/charsetdetect;1?type=zh_parallel_state_machine,{fcacef23-2b40-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/collation-factory;1,{a1b72850-a999-11d2-9119-006008a6edf6} +@mozilla.org/layout/contentserializer;1?mimetype=text/plain,{6030f7ef-32ed-46a7-9a63-6a5d3f90445f} +@mozilla.org/inspector/dom-view;1,{fb5c1775-1bbd-4b9c-abb0-ae7acd29e87e} +@mozilla.org/embeddor.implemented/web-content-handler-registrar;1,{792a7e82-06a0-437c-af63-b2d12e808acc} +@mozilla.org/uriloader/content-handler;1?type=image/gif,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/offlinecacheupdate;1,{e56f5e01-c7cc-4675-a9d7-b8f1e4127295} +@mozilla.org/geolocation;1,{01e1c3ff-094a-d048-44b4-62d29c7b4f39} +@mozilla.org/embedcomp/controller-command-table;1,{670ee5da-6ad5-11d7-9950-000393636592} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-roman,{7b8556a1-ec79-11d2-8aac-00600811a836} +@mozilla.org/image/request;1,{20557898-1dd2-11b2-8f65-9c462ee2bc95} +@mozilla.org/autoconfiguration;1,{e036c738-1dd1-11b2-9392-9d94aa74b0c5} +@mozilla.org/network/protocol;1?name=wyciwyg,{e7509b46-2eb2-410a-9d7c-c3ce73284d01} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-turkish,{7b8556b2-ec79-11d2-8aac-00600811a836} +@mozilla.org/streamconv;1?from=uncompressed&to=deflate,{461cd5dd-73c6-47a4-8cc3-603b37d84a61} +@mozilla.org/svg/svg-document;1,{b7f44954-11d1-11b2-8c2e-c2feab4186bc} +@mozilla.org/rdf/serializer;1?format=ntriples,{0a5cd734-eb65-4d14-88a0-9f0bb2aba206} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1252,{7b8556ac-ec79-11d2-8aac-00600811a836} +@mozilla.org/network/protocol;1?name=moz-gnomevfs,{9b6dc177-a2e4-49e1-9c98-0a8384de7f6c} +@mozilla.org/intl/charsetdetect;1?type=zhtw_parallel_state_machine,{ea06d4e3-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-10,{ba6151b0-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/uriloader/content-handler;1?type=application/http-index-format,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/network/simple-stream-listener;1,{fb8cbf4e-4701-4ba1-b1d6-5388e041fb67} +@mozilla.org/browser/directory-provider;1,{6deb193c-f87d-4078-bc78-5e64655b4d62} +@mozilla.org/layout/xmlfragmentsink;1,{4b664e54-72a2-4bbf-a5c2-66d4dc3066a0} +@mozilla.org/content-pref/service;1,{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7} +@mozilla.org/intl/unicode/decoder;1?charset=VISCII,{6394eeae-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/layout/xul-boxobject-scrollbox;1,{56e2ada8-4631-11d4-ba11-001083023c1e} +@mozilla.org/network/load-group;1,{e1c61582-2a84-11d3-8cce-0060b0fc14a3} +@mozilla.org/layout/xul-boxobject-tree;1,{3b581fd4-3497-426c-8f61-3658b971cb80} +@mozilla.org/alerts-service;1,{a0ccaaf8-09da-44d8-b250-9ac3e93c8117} +@mozilla.org/intl/unicode/encoder;1?charset=x-euc-tw,{379c2776-ec77-11d2-8aac-00600811a836} +@mozilla.org/browser/shell-service;1,{63c7b9f4-0cc8-43f8-b666-0a661655cb73} +@mozilla.org/intl/unicode/encoder;1?charset=x-adobe-euro,{822cb9ae-6421-4484-b3c3-00805f8a6670} +@mozilla.org/widget/lookandfeel;1,{a61e6398-2057-40fd-9c81-873b908d24e7} +@mozilla.org/browser/placesTransactionsService;1,{c0844a84-5a12-4808-80a8-809cb002bb4f} +@mozilla.org/intl/unicode/encoder;1?charset=IBM862,{2d524fda-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/network/file-output-stream;1,{c272fee0-c7e9-11d3-8cda-0060b0fc14a3} +@mozilla.org/network/protocol/about;1?what=credits,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/content/contentutils2;1,{6f8366c7-2195-42ce-a149-48e26aeb9c24} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1258,{6394eea3-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/protocol;1?name=about,{9e3b6c90-2f75-11d3-8cd0-0060b0fc14a3} +@mozilla.org/content/style-sheet-service;1,{fcca6f83-9f7d-44e4-a74b-b59433e6c8c3} +@mozilla.org/uriloader/content-handler;1?type=image/png,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/chrome/chrome-registry;1,{47049e42-1d87-482a-984d-56ae185e367a} +@mozilla.org/appshell/trytoclose;1,{b69155f4-a8bf-453d-8653-91d1456e1d3d} +@mozilla.org/image/decoder;2?type=image/x-png,{36fa00c2-1dd2-11b2-be07-d16eeb4c50ed} +@mozilla.org/cookieService;1,{c375fa80-150f-11d6-a618-0010a401eb10} +@mozilla.org/xpcom/ini-processor-factory;1,{6ec5f479-8e13-4403-b6ca-fe4c2dca14fd} +@mozilla.org/principal;1,{36102b6b-7b62-451a-a1c8-a0d456c92dc5} +@mozilla.org/nsCMSDecoder;1,{9dcef3a4-a3bc-11d5-ba47-00108303b117} +@mozilla.org/intl/unicode/encoder;1?charset=EUC-JP,{45c23a20-d71c-11d2-8aac-00600811a836} +@mozilla.org/crypto/fips-info-service;1,{ff9fbcd7-9517-4334-b97a-ceed78909974} +@mozilla.org/intl/charsetdetect;1?type=ja_parallel_state_machine,{12bb8f1b-2389-11d3-b3bf-00805f8a6670} +@mozilla.org/content/element/html;1?name=audio,{1d40026b-4c44-4f6f-b158-26bb5e9c65e9} +@mozilla.org/security/script/nameset;1,{7c02eadc-0076-4d03-998d-80d779c48589} +@mozilla.org/network/protocol;1?name=moz-icon,{d0f9db12-249c-11d5-9905-001083010e9b} +@mozilla.org/uriloader/handler-service;1,{32314cc8-22f7-4f7f-a645-1a45453ba6a6} +@mozilla.org/security/pkcs11moduledb;1,{ff9fbcd7-9517-4334-b97a-ceed78909974} +@mozilla.org/widgets/child_window/gtk;1,{2d96b3d1-c051-11d1-a827-0040959a28c9} +@mozilla.org/autocomplete/search;1?name=form-history,{895db6c7-dbdf-40ea-9f64-b175033243dc} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-5,{660d8ca7-f763-11d2-8aad-00600811a836} +@mozilla.org/browser/places/import-export-service;1,{6fb0c970-e1b1-11db-8314-0800200c9a66} +@mozilla.org/toolkit/URLFormatterService;1,{e6156350-2be8-11db-a98b-0800200c9a66} +@mozilla.org/xml/xml-document;1,{a6cf9063-15b3-11d2-932e-00805f8add32} +@mozilla.org/image/decoder;2?type=image/pjpeg,{5871a422-1dd2-11b2-ab3f-e2e56be5da9c} +@mozilla.org/network/buffered-input-stream;1,{9226888e-da08-11d3-8cda-0060b0fc14a3} +@mozilla.org/intl/nslanguageatomservice;1,{a6cf9120-15b3-11d2-932e-00805f8add32} +@mozilla.org/feed-textconstruct;1,{b992ddcd-3899-4320-9909-924b3e72c922} +@mozilla.org/intl/unicode/encoder;1?charset=Adobe-Symbol-Encoding,{21dd6a02-413c-11d3-b3c3-00805f8a6670} +@mozilla.org/image/decoder;2?type=image/x-icon,{cb3ede1a-0fa5-4e27-aafe-0f7801e5a1f1} +@mozilla.org/uriloader/content-handler;1?type=application/xhtml+xml,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/security/keyobjectfactory;1,{a39e0e9d-e567-41e3-b12c-5df67f18174d} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-16LE,{ba6151b5-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/widget/native-key-bindings;1?type=textarea,{2a898043-180f-4c8b-8e54-410c7a540f27} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-15,{6394eeb2-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/spellchecker-inline;1,{9fe5d975-09bd-44aa-a01a-66402ea28657} +@mozilla.org/htmlparanoidfragmentsink;2,{a47ef526-6e48-4574-9d60-3164e271f75e} +@mozilla.org/network/safe-file-output-stream;1,{a181af0d-68b8-4308-94db-d4f859058215} +@mozilla.org/streamconv;1?from=uncompressed&to=gzip,{461cd5dd-73c6-47a4-8cc3-603b37d84a61} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-6-E,{495eca47-0a5c-11d4-a135-005004832142} +@mozilla.org/content/css-parser;1,{2e363d60-872e-11d2-b531-000000000000} +@mozilla.org/rdf/datasource;1?name=window-mediator,{c744ca3d-840b-460a-8d70-7ce63c51c958} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1250,{7c657d14-ec5e-11d2-8aac-00600811a836} +@mozilla.org/toolkit/console-clh;1,{2cd0c310-e127-44d0-88fc-4435c9ab4d4b} +@mozilla.org/transformiix-nodeset;1,{5d5d92cd-6bf8-11d9-bf4a-000a95dc234c} +@mozilla.org/uriloader/content-handler;1?type=image/svg+xml,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-32BE,{ba6151b3-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/nslocaleservice;1,{c8e518c1-47ae-11d3-91cd-00105aa3f7dc} +@mozilla.org/rdf/content-sink;1,{0958b101-9ada-11d2-8ebc-00805f29f370} +@mozilla.org/network/urichecker;1,{cf3a0e06-1dd1-11b2-a904-ac1d6da77a02} +@mozilla.org/dom/storage;2,{27aecc62-7777-428e-b34c-5973a47b8298} +@mozilla.org/intl/unicode/encoder;1?charset=x-mtextra,{0cb0d9a0-f503-11d3-b32f-004005a7a7e4} +@mozilla.org/uriloader/content-handler;1?type=application/vnd.mozilla.xul+xml,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/browser/livemark-service;2,{dca61eb5-c7cd-4df1-b0fb-d0722baba251} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-5,{660d8ca2-f763-11d2-8aad-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=x-user-defined,{9416bfb2-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/preferences;1,{dc26e0e0-ca94-11d1-a9a4-00805f8a7ac4} +@mozilla.org/uriloader/content-handler;1?type=image/jpg,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/network/protocol;1?name=data,{b6ed3030-6183-11d3-a178-0050041caf44} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-8-E,{495eca42-0a5c-11d4-a135-005004832142} +@mozilla.org/parser/parser-service;1,{a6cf9112-15b3-11d2-932e-00805f8add32} +@mozilla.org/intl/unicode/encoder;1?charset=x-viet-tcvn5712,{6394eebd-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/browser/httpindex-service;1,{2587e382-1324-11d4-a652-eadbb2be3484} +@mozilla.org/gfx/fontmetrics;1,{6049b263-c1e6-11d1-a827-0040959a28c9} +@mozilla.org/intl/stringcharsetdetect;1?type=ukprob,{2002f784-3960-11d3-b3c3-00805f8a6670} +@mozilla.org/network/protocol/about;1?what=blocked,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/widget/native-key-bindings;1?type=editor,{f916ebfb-78ef-464b-94d0-a6f2ca3200ae} +@mozilla.org/js/xpc/ContextStackIterator;1,{05bae29d-8aef-486d-84aa-53f48f146811} +@mozilla.org/browser/session-history-entry;1,{bfd1a791-ad9f-11d3-bdc7-0050040a9b44} +@joehewitt.com/firebug;1,{a380e9c0-cb39-11da-a94d-0800200c9a66} +@mozilla.org/feed-result;1,{072a5c3d-30c6-4f07-b87f-9f63d51403f2} +@mozilla.org/userinfo;1,{14c13684-1dd2-11b2-9463-bb10ba742554} +@mozilla.org/xpfe/http-index-format-factory-constructor,{82776710-5690-11d3-be36-00104bde6048} +@mozilla.org/intl/unicode/encoder;1?charset=IBM852,{2d524fd7-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/browser/nav-history-service;1,{88cecbb7-6c63-4b3b-8cd4-84f3b8228c69} +@mozilla.org/gnome-vfs-service;1,{5f43022c-6194-4b37-b26d-e41024625264} +@mozilla.org/nsFormSigningDialog;1,{a4bd2161-7892-4389-8d5a-3111a6d17ec7} +@mozilla.org/xhtmlparanoidfragmentsink;2,{ad78bbf0-e261-482b-32b3-78a7b2afc8f7} +@mozilla.org/js/xpc/ID;1,{f24a14f0-4fa1-11d3-9894-006008962422} +@mozilla.org/geolocation/service;1,{0404d02a-01ca-aaab-4762-944b1bf2f7b5} +@mozilla.org/intl/stringcharsetdetect;1?type=zhtw_parallel_state_machine,{ea06d4e6-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-roman,{7b8556af-ec79-11d2-8aac-00600811a836} +@mozilla.org/nsCMSSecureMessage;1,{5fb907e0-1dd2-11b2-a7c0-f14c416a62a1} +@mozilla.org/embedding/browser/nsWebBrowserPersist;1,{7e677795-c582-4cd1-9e8d-8271b3474d2a} +@mozilla.org/toolkit/remote-service;1,{c0773e90-5799-4eff-ad03-3ebcd85624ac} +@mozilla.org/exslt/regexp;1,{18a03189-067b-4978-b4f1-bafe35292ed6} +@mozilla.org/intl/stringbundle;1,{d85a17c1-aa7c-11d2-9b8c-00805f8a16d9} +@mozilla.org/user_cert_picker;1,{735959a1-af01-447e-b02d-56e968fa52b4} +@mozilla.org/browser/shistory;1,{7294fe9c-14d8-11d5-9882-00c04fa02f40} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-7,{77cfaaf2-1cf4-11d3-8aaf-00600811a836} +@mozilla.org/gfx/devicecontext;1,{6049b262-c1e6-11d1-a827-0040959a28c9} +@mozilla.org/browser/final-clh;1,{47cd0651-b1be-4a0f-b5c4-10e5a573ef71} +@mozilla.org/network/input-stream-pump;1,{ccd0e960-7947-4635-b70e-4c661b63d675} +@mozilla.org/embedcomp/prompt-service;1,{a2112d6a-0e28-421f-b46a-25c0b308cbd0} +@mozilla.org/intl/entityconverter;1,{9e9b565a-8e52-4c1a-8805-b2b91655f874} +@mozilla.org/intl/unicode/decoder;1?charset=x-imap4-modified-utf7,{b57f97c1-0d70-11d3-8aae-00600811a836} +@mozilla.org/intl/unicode/encoder;1?charset=x-user-defined,{9416bfb4-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/typeaheadfind;1,{e7f70966-9a37-48d7-8aeb-35998f31090e} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-13,{ba6151b1-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=x-mathematica2,{7e6e57c0-e2f2-11d3-b32f-004005a7a7e4} +@mozilla.org/intl/unicode/decoder;1?charset=x-johab,{d9b1f97f-cfa0-80b6-fb92-9972e48e3dcc} +@mozilla.org/prefetch-service;1,{6b8bdffc-3394-417d-be83-a81b7c0f63bf} +@mozilla.org/embedcomp/nbalert-service;1,{a2112d6a-0e28-421f-b46a-25c0b308cbd0} +@mozilla.org/network/socket-provider-service;1,{ed394ba0-5472-11d3-bbc8-0000861d1237} +@mozilla.org/zipwriter;1,{430d416c-a722-4ad1-be98-d9a445f85e3f} +@mozilla.org/rdf/datasource;1?name=local-store,{df71c6f0-ec53-11d2-bdca-000064657374} +@mozilla.org/preferences-service;1,{1cd91b88-1dd2-11b2-92e1-ed22ed298000} +@mozilla.org/nsSSLCertErrorDialog;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/streamconv;1?from=gzip&to=uncompressed,{66230b2b-17fa-4bd3-abf4-07986151022d} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1255,{ba6151a1-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/scriptableunicodeconverter,{0a698c44-3bff-11d4-9649-00c0ca135b4e} +@mozilla.org/nsCertPickDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/content/range-utils;1,{a6cf9126-15b3-11d2-932e-00805f8add32} +@mozilla.org/editor/txtsrvfiltermail;1,{7fbd2146-5ff4-4674-b069-a7bbce66e773} +@mozilla.org/network/protocol;1?name=jar,{c7e410d4-85f2-11d3-9f63-006008a6efe9} +@mozilla.org/pref-relativefile;1,{2f977d4f-5485-11d4-87e2-0010a4e75ef2} +@mozilla.org/gfx/printsession;1,{2f977d53-5485-11d4-87e2-0010a4e75ef2} +@mozilla.org/mime;1,{a7f800e0-4306-11d4-98d0-001083010e9b} +@mozilla.org/browser/global-history;2,{88cecbb7-6c63-4b3b-8cd4-84f3b8228c69} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1258,{6394eeb3-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/charsetdetectionadaptor;1,{12bb8f17-2389-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=VISCII,{6394eebf-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/profile/migrator;1?app=browser&type=phoenix,{78481e4a-50e4-4489-b68a-ef82670ed63f} +@mozilla.org/intl/unicode/encoder;1?charset=Big5-HKSCS,{ba6151bc-ec62-11d2-8aac-00600811a836} +@mozilla.org/streamconv;1?from=deflate&to=uncompressed,{66230b2b-17fa-4bd3-abf4-07986151022d} +@mozilla.org/layout/htmlsanitizer;1,{feca3c34-205e-4ae5-bd1c-03c686ff012b} +@mozilla.org/cookiemanager;1,{aaab6710-0f2c-11d5-a53b-0010a401eb10} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-2,{7b8556a6-ec79-11d2-8aac-00600811a836} +@mozilla.org/autocomplete/search;1?name=search-autocomplete,{aa892eb4-ffbf-477d-9f9a-06c995ae9f27} +@mozilla.org/intl/unicode/encoder;1?charset=x-mathematica1,{758e4f20-e2f2-11d3-b32f-004005a7a7e4} +@mozilla.org/network/url-parser;1?auth=no,{78804a84-8173-42b6-bb94-789f0816a810} +@mozilla.org/embedcomp/printingprompt-service;1,{e042570c-62de-4bb6-a6e0-798e3c07b4df} +@mozilla.org/image/encoder;2?type=image/jpeg,{ac2bb8fe-eeeb-4572-b40f-be03932b56e0} +@mozilla.org/network/network-link-service;1,{75a500a2-0030-40f7-86f8-63f225b940ae} +@mozilla.org/intl/wbrk;1,{2bf64765-997f-450d-af96-3028d1a902b0} +@mozilla.org/charset-converter-manager;1,{3c1c0163-9bd0-11d3-9d09-0050040007b2} +@mozilla.org/security/streamcipher;1,{dbfcbe4a-10f7-4d6f-a481-68e6d6b71d21} +@mozilla.org/eventlistenerservice;1,{baa34652-f1f1-4185-b224-244ee82a413a} +@mozilla.org:/content/content-area-dragdrop;1,{1f34bc80-1bc7-11d6-a384-d705dd0746fc} +@mozilla.org/layout/documentEncoder;1?type=text/html,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/rdf/rdf-service;1,{bfd05264-834c-11d2-8eac-00805f29f370} +@mozilla.org/security/certoverride;1,{67ba681d-5485-4fff-952c-2ee337ffdcd6} +@mozilla.org/layout/content-policy;1,{0e3afd3d-eb60-4c2b-963b-56d7c439f124} +@mozilla.org/secure_browser_ui;1,{cc75499a-1dd1-11b2-8a82-ca410ac907b8} +@mozilla.org/browser/history-entry;1,{a41661d5-1417-11d5-9882-00c04fa02f40} +@mozilla.org/htmlparanoidfragmentsink;1,{a47e9526-6e48-4574-9d6c-3164e271f74e} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-10,{ba6151ab-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/widget/dragservice;1,{8b5314bb-db01-11d2-96ce-0060b0fb9956} +@mozilla.org/channelclassifier,{ce02d538-0217-47a3-a589-b51790fdd8ce} +@mozilla.org/layout/xul-boxobject-menu;1,{aa40253b-4c42-4056-8132-37bcd07862fd} +@mozilla.org/embedcomp/base-command-controller;1,{bf88b48c-fd8e-40b4-ba36-c7c3ad6d8ac9} +@mozilla.org/intl/unicode/decoder;1?charset=IBM864i,{2d524fdc-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/wifi/monitor;1,{3ff8fb9f-ee63-48df-89f0-dace0242fd82} +@mozilla.org/plugin/host;1,{23e8fd98-a625-4b08-be1a-f7cc18a5b106} +@mozilla.org/embedcomp/command-params;1,{f7fa4581-238e-11d5-a73c-ab64fb68f2bc} +@mozilla.org/uriloader/content-handler;1?type=text/xml,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/intl/unicode/encoder;1?charset=IBM857,{2d524fd9-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/layout/xul-boxobject-listbox;1,{c2710d40-6f4d-4b7f-9778-76ae5166648c} +@mozilla.org/uriloader;1,{9f6d5d40-90e7-11d3-af80-00a024ffc08c} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1255,{ba6151a3-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=x-tamilttf-0,{a431b276-f77d-4b83-9b37-872cf2fbcc2a} +@mozilla.org/feed-generator;1,{414af362-9ad8-4296-898e-62247f25a20e} +@mozilla.org/intl/lbrk;1,{2bf64764-997f-450d-af96-3028d1a902b0} +@mozilla.org/uriloader/local-handler-app;1,{bc0017e3-2438-47be-a567-41db58f17627} +@mozilla.org/intl/unicode/encoder;1?charset=EUC-KR,{379c2778-ec77-11d2-8aac-00600811a836} +@mozilla.org/xmlextras/xmlhttprequest;1,{d164e770-4157-11d4-9a42-000064657374} +@mozilla.org/layout/documentEncoder;1?type=text/plain,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-hebrew,{6803cacd-1e3b-11d5-a145-005004832142} +@mozilla.org/filepicker;1,{bd57cee8-1dd1-11b2-9fe7-95cf4709aea3} +@mozilla.org/accessibilityService;1,{de401c37-9a7f-4278-a6f8-3de2833989ef} +@mozilla.org/xml/xpointer;1?scheme=xpath1,{0c351177-0159-4500-86b0-a219dfde4258} +@mozilla.org/network/protocol/about;1?what=sessionrestore,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-gurmukhi,{6803cace-1e3b-11d5-a145-005004832142} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1250,{7b8556aa-ec79-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-16,{a0f827e1-8ab6-11d5-a14b-005004832142} +@mozilla.org/content/xmlhttprequest-bad-cert-handler;1,{dbded6ec-edbf-4054-a834-287b82c260f9} +@mozilla.org/layout/htmlfragmentsink;2,{13111d00-ce81-11d6-8082-ecf3665af67c} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-2,{7c657d11-ec5e-11d2-8aac-00600811a836} +@mozilla.org/image/decoder;2?type=image/bmp,{78c61626-4d1f-4843-9364-4652d98ff6e1} +@mozilla.org/image/decoder;2?type=image/jpeg,{5871a422-1dd2-11b2-ab3f-e2e56be5da9c} +@mozilla.org/feed-entry;1,{8e4444ff-8e99-4bdd-aa7f-fb3c1c77319f} +@mozilla.org/streamconv;1?from=x-gzip&to=uncompressed,{66230b2b-17fa-4bd3-abf4-07986151022d} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-IR-111,{9416bfb3-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=IBM864,{2d524fdb-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/content/namespacemanager;1,{d9783472-8fe9-11d2-9d3c-0060088f9ff7} +@mozilla.org/rdf/datasource;1?name=xml-datasource,{7baf62e0-8e61-11d2-8eb1-00805f29f370} +@mozilla.org/uriloader/content-handler;1?type=image/jpeg,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/embedding/browser/nsWebBrowser;1,{f1eac761-87e9-11d3-af80-00a024ffc08c} +@mozilla.org/network/proxy-auto-config;1,{63ac8c66-1dd2-11b2-b070-84d00d3eaece} +@mozilla.org/system-preferences;1,{549abb24-7c9d-4aba-915e-7ce0b716b32f} +@mozilla.org/systemprincipal;1,{4a6212db-accb-11d3-b765-0060b0b6cecb} +@mozilla.org/network/protocol/about;1?what=neterror,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/login-manager/storage/legacy;1,{e09e4ca6-276b-4bb4-8b71-0635a3a2a007} +@mozilla.org/streamconv;1?from=uncompressed&to=x-gzip,{461cd5dd-73c6-47a4-8cc3-603b37d84a61} +@mozilla.org/network/incremental-download;1,{a62af1ba-79b3-4896-8aaf-b148bfce4280} +@mozilla.org/xtf/xtf-service;1,{4ec832da-6ae7-4185-807b-daddcb5da37a} +@mozilla.org/embedcomp/command-manager;1,{64edb481-0c04-11d5-a73c-e964b968b0bc} +@mozilla.org/intl/unicode/decoder;1?charset=IBM850,{2d524fd0-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/intl/stringcharsetdetect;1?type=ruprob,{2002f783-3960-11d3-b3c3-00805f8a6670} +@mozilla.org/network/file-input-stream;1,{be9a53ae-c7e9-11d3-8cda-0060b0fc14a3} +@mozilla.org/no-data-protocol-content-policy;1,{ac9e3e82-bfbd-4f26-941e-f58c8ee178c1} +@mozilla.org/libjar/zip-reader;1,{7526a738-9632-11d3-8cd9-0060b0fc14a3} +@mozilla.org/document-charset-info;1,{d25e0511-2bae-11d4-9d10-0050040007b2} +@mozilla.org/network/protocol/about;1?what=privatebrowsing,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/download-manager;1,{edb0490e-1dd1-11b2-83b8-dbf8d85906a6} +@mozilla.org/xre/runtime;1,{95d89e3e-a169-41a3-8e56-719978e15b12} +@mozilla.org/readconfig;1,{ba5bc4c6-1dd1-11b2-bb89-b844c6ec0339} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-7,{7b8556a8-ec79-11d2-8aac-00600811a836} +@mozilla.org/content/subtree-content-iterator;1,{a6cf90e5-15b3-11d2-932e-00805f8add32} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-16BE,{ba6151b2-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/network/protocol;1?name=file,{fbc81170-1f69-11d3-9344-00104ba0fd40} +@mozilla.org/offlinecacheupdate-service;1,{ec06f3fc-70db-4ecd-94e0-a6e91ca44d8a} +@mozilla.org/browser/nav-bookmarks-service;1,{9de95a0c-39a4-4d64-9a53-17940dd7cabb} +@mozilla.org/widget/image-to-gdk-pixbuf;1,{fc2389b8-c650-4093-9e42-b05e5f0685b7} +@mozilla.org/txttohtmlconv;1,{77c0e42a-1dd2-11b2-8ebf-edc6606f2f4b} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-devanagari,{6803cac4-1e3b-11d5-a145-005004832142} +@mozilla.org/network/protocol/about;1?what=memory,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/network/protocol;1?name=https,{dccbe7e4-7750-466b-a557-5ea36c8ff24e} +@mozilla.org/intl/unicode/decoder;1?charset=Shift_JIS,{0e6892c1-a9ad-11d2-b3ae-00805f8a6670} +@mozilla.org/network/http-authenticator;1?scheme=negotiate,{75c80fd0-accb-432c-af59-ec60668c3990} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-cyrillic,{6394eea9-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-hebrew,{6803cacc-1e3b-11d5-a145-005004832142} +@mozilla.org/streamconv;1?from=application/x-unknown-content-type&to=*/*,{7d7008a0-c49a-11d3-9b22-0080c7cb1080} +@mozilla.org/rdf/resource-factory;1,{0f78da56-8321-11d2-8eac-00805f29f370} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-32BE,{ba6151ae-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/rdf/datasource;1?name=charset-menu,{42c52b81-a200-11d3-9d0b-0050040007b2} +@mozilla.org/intl/metacharset;1,{218f2ac0-0a48-11d3-b3ba-00805f8a6670} +@mozilla.org/feed;1,{5d0cfa97-69dd-4e5e-ac84-f253162e8f9a} +@mozilla.org/content/pre-content-iterator;1,{80d7e247-d4b8-45d7-bb59-6f1dd56f384c} +@mozilla.org/security/x509certdb;1,{fb0bbc5c-452e-4783-b32c-80124693d871} +@mozilla.org/view-manager;1,{c95f1831-c376-11d1-b721-00600891d8c9} +@mozilla.org/image/decoder;2?type=image/png,{36fa00c2-1dd2-11b2-be07-d16eeb4c50ed} +@mozilla.org/moz/jssubscript-loader;1,{929814d6-1dd2-11b2-8e08-82fa0a339b00} +@mozilla.org/security/sdr;1,{0c4f1ddc-1dd2-11b2-9d95-f2fdf113044b} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1256,{ba6151a2-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/extensions/manager;1,{8a115faa-7dcb-4e8f-979b-5f53472f51cf} +@mozilla.org/spellchecker/i18nmanager;1,{aeb8936f-219c-4d3c-8385-d9382daa551a} +@mozilla.org/intl/unicode/decoder;1?charset=x-gbk,{ba61519e-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-6-I,{495eca44-0a5c-11d4-a135-005004832142} +@mozilla.org/dirIndex;1,{f6913e2e-1dd1-11b2-84be-f455dee342af} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-croatian,{6394eea7-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/appshell/window-mediator;1,{0659cb83-faad-11d2-8e19-b206620a657c} +@mozilla.org/network/protocol/about;1?what=rights,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/network/simple-uri;1,{e0da1d70-2f7b-11d3-8cd0-0060b0fc14a3} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-gujarati,{6803caca-1e3b-11d5-a145-005004832142} +@mozilla.org/intl/unicode/decoder;1?charset=GEOSTD8,{6394eeaf-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-7,{af7a9951-aa48-11d2-b3ae-00805f8a6670} +@mozilla.org/security/datasignatureverifier;1,{296d76aa-275b-4f3c-af8a-30a4026c18fc} +@mozilla.org/content/range;1,{56ad2981-8a87-11d2-918c-0080c8e44db5} +@mozilla.org/network/default-auth-prompt;1,{ca200860-4696-40d7-88fa-4490d423a8ef} +@mozilla.org/places/sync;1,{c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a} +@mozilla.org/network/protocol/about;1?what=robots,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/embedcomp/window-watcher;1,{a21bfa01-f349-4394-a84c-8de5cf0737d0} +@mozilla.org/network/protocol/about;1?what=licence,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/browser/default-browser-clh;1,{f57899d0-4e2c-4ac6-9e29-50c736103b0c} +@mozilla.org/layout/documentEncoder;1?type=text/xml,{e7ba1480-1dea-11d3-830f-00104bed045e} +@mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/*,{229fa115-9412-4d32-baf3-2fc407f76fb1} +@mozilla.org/intl/stringcharsetdetect;1?type=ko_parallel_state_machine,{ea06d4e4-2b3d-11d3-b3bf-00805f8a6670} +@mozilla.org/appshell/component/browser/instance;1,{5551a1e0-5a66-11d3-806a-00600811a9c3} +@mozilla.org/updates/timer-manager;1,{b322a5c0-a419-484e-96ba-d7182163899f} +@mozilla.org/uriloader/content-handler;1?type=text/rdf,{5d0ce354-df01-421a-83fb-7ead0990c24e} +@mozilla.org/widget/clipboard;1,{8b5314ba-db01-11d2-96ce-0060b0fb9956} +@mozilla.org/scripterror;1,{e38e53b9-5bb0-456a-b553-579370cb1567} +@mozilla.org/nsCMSEncoder;1,{a15789aa-8903-462b-81e9-4aa2cff4d5cb} +@mozilla.org/content/element/html;1?name=option,{a6cf90f5-15b3-11d2-932e-00805f8add32} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-13,{ba6151ac-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/spellchecker;1,{8227f019-afc7-461e-b030-9f185d7a0e29} +@mozilla.org/network/async-stream-copier;1,{e746a8b1-c97a-4fc5-baa4-66607521bd08} +@mozilla.org/image/cache;1,{9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7} +@mozilla.org/intl/unicodenormalizer;1,{a665e49a-f3e6-4fed-9f31-f7c568a29899} +@mozilla.org/editor/editordocstatecontroller;1,{50e95301-17a8-11d4-9f7e-dd530d5f057c} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-16,{d673255d-1184-400a-b0b5-ee9d1295bd85} +@mozilla.org/uriclassifierservice,{5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6} +@mozilla.org/textservices/textservicesdocument;1,{019718e3-cdb5-11d2-8d3c-000000000000} +@mozilla.org/spellcheck/dir-provider;1,{64d6174c-1496-4ffd-87f2-da2670f88934} +@mozilla.org/embedcomp/rangefind;1,{471f4944-1dd2-11b2-87ac-90be0a51d609} +@mozilla.org/login-manager;1,{cb9e0de8-3598-4ed7-857b-827f011ad5d8} +@mozilla.org/streamconv;1?from=multipart/byteranges&to=*/*,{7584ce90-5b25-11d3-a175-0050041caf44} +@mozilla.org/network/protocol;1?name=javascript,{bfc310d2-38a0-11d3-8cd3-0060b0fc14a3} +@mozilla.org/geolocation/prompt;1,{c6e8c44d-9f39-4af7-bcc0-76e38a8310f5} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-8-E,{495eca49-0a5c-11d4-a135-005004832142} +@mozilla.org/network/protocol;1?name=chrome,{61ba33c0-3031-11d3-8cd0-0060b0fc14a3} +@mozilla.org/toolkit/command-line;1,{23bcc750-dc20-460b-b2d4-74d8f58d3615} +@mozilla.org/intl/unicode/encoder;1?charset=x-tscii,{d2800356-c2d7-4e05-a884-79fe566af1cf} +@mozilla.org/uriloader/external-protocol-service;1,{a7f800e0-4306-11d4-98d0-001083010e9b} +@mozilla.org/rdf/datasource;1?name=extensions,{69bb8313-2d4f-45ec-97e0-d39da58ecce9} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-7,{77cfaaf1-1cf4-11d3-8aaf-00600811a836} +@mozilla.org/browser/annotation-service;1,{5e8d4751-1852-434b-a992-2c6d2a25fa46} +@mozilla.org/system-preference-service;1,{94f1de09-d0e5-4ca8-94c2-98b049316b7f} +@mozilla.org/intl/unicode/encoder;1?charset=x-ttf-cmsy,{e332db00-e076-11d3-b32f-004005a7a7e4} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-11,{776588a6-86d5-47e2-b6b3-992810078202} +@mozilla.org/intl/unicode/encoder;1?charset=x-imap4-modified-utf7,{b57f97c2-0d70-11d3-8aae-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=x-viet-vps,{6394eeb0-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/layout/htmlfragmentsink;1,{d4f2b600-b5c1-11d6-b483-cc97c63e567c} +@mozilla.org/security/pkcs11;1,{74b7a390-3b41-11d4-8a80-006008c844c3} +@mozilla.org/layout/xmlfragmentsink;2,{4dc30689-929d-425e-a709-082c6294e542} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-croatian,{6394eeb7-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/protocol/about;1?what=support,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/plugin-bindings;1,{12663f3a-a311-4606-83eb-b6b9108dcc36} +@mozilla.org/url-classifier/dbservice;1,{5eb7c3c1-ec1f-4007-87cc-eefb37d68ce6} +@mozilla.org/intl/unicode/decoder;1?charset=IBM862,{2d524fd4-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/document-transformer;1?type=xslt,{bacd8ad0-552f-11d3-a9f7-000064657374} +@mozilla.org/image/decoder;2?type=image/vnd.microsoft.icon,{cb3ede1a-0fa5-4e27-aafe-0f7801e5a1f1} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-IR-111,{9416bfb1-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/editor/htmleditor;1,{ed0244e0-c144-11d2-8f4c-006008159b0c} +@mozilla.org/network/http-auth-manager;1,{36b63ef3-e0fa-4c49-9fd4-e065e85568f4} +@joehewitt.com/firebug-trace-service;1,{d2ac51bc-1622-4d4d-85cb-f8e8b5805cb9} +@mozilla.org/xul/xul-document;1,{541afcb2-a9a3-11d2-8ec5-00805f29f370} +@mozilla.org/url-classifier/jslib;1,{26a4a019-2827-4a89-a85c-5931a678823a} +@mozilla.org/saxparser/attributes;1,{7bb40992-77eb-43db-9a4e-39d3bcc383ae} +@mozilla.org/intl/unicode/encoder;1?charset=KOI8-U,{6394eeb6-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/focus-manager;1,{cf7fd51f-aba2-44c1-9ff0-11f7508efcd4} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-gurmukhi,{6803cacf-1e3b-11d5-a145-005004832142} +@mozilla.org/intl/unicode/decoder;1?charset=windows-936,{9416bfc0-1f93-11d3-b3bf-00805f8a6670} +@mozilla.org/transfer;1,{e3fa9d0a-1dd1-11b2-bdef-8c720b597445} +@mozilla.org/rdf/container-utils;1,{d4214e92-fb94-11d2-bdd8-00104bde6048} +@mozilla.org/rdf/datasource;1?name=httpindex,{2587e382-1324-11d4-a652-eadbb2be3484} +@mozilla.org/intl/unicode/decoder;1?charset=windows-874,{6394eea4-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/browser/session-history-transaction;1,{bfd1a792-ad9f-11d3-bdc7-0050040a9b44} +@mozilla.org/autocomplete/simple-result;1,{2ee3039b-2de4-43d9-93b0-649beacff39a} +@mozilla.org/scriptableinterfaces;1,{fe4f7592-c1fc-4662-ac83-538841318803} +@mozilla.org/security/random-generator;1,{be65e2b7-fe46-4e0f-88e0-4b385db4d68a} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-4,{660d8ca6-f763-11d2-8aad-00600811a836} +@mozilla.org/profile/migrator;1?app=browser&type=dogbert,{24f92fae-f793-473b-8061-713408bd11d5} +@mozilla.org/network/content-sniffer;1,{7d7008a0-c49a-11d3-9b22-0080c7cb1080} +@mozilla.org/intl/unicode/decoder;1?charset=HZ-GB-2312,{ba61519a-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/rdf/xml-parser;1,{a4048e94-1dd1-11b2-a676-8a06c086cc7d} +@mozilla.org/nsTokenPasswordDialogs;1,{518e071f-1dd2-11b2-937e-c45f14def778} +@mozilla.org/intl/unicode/encoder;1?charset=x-t1-cmsy,{e768ebef-70f9-4fe3-8835-4f4f3fd996e2} +@mozilla.org/intl/unicode/decoder;1?charset=TIS-620,{66634f68-be19-42d0-a4ca-d1c21fa059b8} +@mozilla.org/network/protocol;1?name=default,{bd6390c8-fbea-11d4-98f6-001083010e9b} +@mozilla.org/toolkit/default-clh;1,{6ebc941a-f2ff-4d56-b3b6-f7d0b9d73344} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-icelandic,{6394eebb-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-2022-JP,{4f76e100-d71c-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-16,{a0f827e2-8ab6-11d5-a14b-005004832142} +@mozilla.org/gfx/fontenumerator;1,{a6cf9115-15b3-11d2-932e-00805f8add32} +@mozilla.org/network/socket-transport-service;1,{c07e81e0-ef12-11d2-92b6-00105a1b0d64} +@mozilla.org/content/element/html;1?name=img,{d6008c40-4dad-11d2-b328-00805f8a3859} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1257,{a578e0a4-f76b-11d2-8aac-00600811a836} +@mozilla.org/browser/download-history;1,{88cecbb7-6c63-4b3b-8cd4-84f3b8228c69} +@mozilla.org/intl/unicode/encoder;1?charset=x-mac-farsi,{6803cac9-1e3b-11d5-a145-005004832142} +@mozilla.org/security/keyobject;1,{eae599aa-ecef-49c6-a8af-6ddcc6feb484} +@mozilla.org/network/stream-listener-tee;1,{831f8f13-7aa8-485f-b02e-77c881cc5773} +@mozilla.org/gfx/printerenumerator;1,{a6cf9129-15b3-11d2-932e-00805f8add32} +@mozilla.org/browser/feeds/result-service;1,{2376201c-bbc6-472f-9b62-7548040a61c6} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1253,{af7a9952-aa48-11d2-b3ae-00805f8a6670} +@mozilla.org/network/protocol/about;1?what=,{1f1ce501-663a-11d3-b7a0-be426e4e69bc} +@mozilla.org/layout/xul-boxobject-popup;1,{6c392c62-1ab1-4de7-bfc6-ed4f9fc7749a} +@mozilla.org/nsSecurityWarningDialogs;1,{8d995d4f-adcc-4159-b7f1-e94af72eeb88} +@mozilla.org/data-document-content-policy;1,{1147d32c-215b-4014-b180-07fe7aedf915} +@mozilla.org/filepicker/fileview;1,{a5570462-1dd1-11b2-9d19-df30a27fbdc4} +@mozilla.org/xul/xul-controllers;1,{1f5c1721-7dc3-11d3-bf87-00105a1b0627} +@mozilla.org/embedcomp/dialogparam;1,{4e4aae11-8901-46cc-8217-dad7c5415873} +@mozilla.org/layout/xul-boxobject;1,{d750a964-2d14-484c-b3aa-8ed7823b5c7b} +@mozilla.org/layout/form-processor;1,{0ae53c0f-8ea2-4916-bedc-717443c3e185} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-8,{7c657d18-ec5e-11d2-8aac-00600811a836} +@mozilla.org/gfx/screenmanager;1,{c401eb80-f9ea-11d3-bb6f-e732b73ebe7c} +@mozilla.org/rdf/container;1,{d4214e93-fb94-11d2-bdd8-00104bde6048} +@mozilla.org/moz/jsloader;1,{6bd13476-1dd2-11b2-bbef-f0ccb5fa64b6} +@mozilla.org/network/protocol/about;1?what=feeds,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/rdf/xml-serializer;1,{0032d852-1dd2-11b2-95f7-e0a1910ed2da} +@mozilla.org/network/dns-service;1,{b0ff4572-dae4-4bef-a092-83c1b88f6be9} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1256,{ba6151a4-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/content/document-loader-factory;1,{fc886801-e768-11d4-9885-00c04fa0cf4b} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-14,{6394eea1-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=Big5,{efc323e1-ec62-11d2-8aac-00600811a836} +@mozilla.org/helperapplauncherdialog;1,{f68578eb-6ec2-4169-ae19-8c6243f0abe1} +@mozilla.org/streamConverters;1,{892ffeb0-3f80-11d3-a16c-0050041caf44} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-4,{660d8ca1-f763-11d2-8aad-00600811a836} +@mozilla.org/content/contentutils;1,{762c4ae7-b923-422f-b97e-b9bfc1ef7bf0} +@mozilla.org/intl/unicode/decoder;1?charset=EUC-JP,{3f6fe6a1-ac0a-11d2-b3ae-00805f8a6670} +@mozilla.org/intl/stringbundle/text-override;1,{6316c6ce-12d3-479e-8f53-e289351412b8} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-2022-JP,{3f6fe6a2-ac0a-11d2-b3ae-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=HZ-GB-2312,{ba61519d-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/browser/shistory-internal;1,{9c47c121-1c6e-4d8f-b904-3ac968116e88} +@mozilla.org/network/socket;2?type=socks4,{f7c9f5f4-4451-41c3-a28a-5ba2447fbace} +@mozilla.org/network/buffered-output-stream;1,{9868b4ce-da08-11d3-8cda-0060b0fc14a3} +@mozilla.org/intl/unicode/encoder;1?charset=IBM866,{ba6151aa-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=x-ttf-cmmi,{73bb7c12-dbab-4ae2-aecf-a0331dec916f} +@mozilla.org/editor/editorspellchecker;1,{75656ad9-bd13-4c5d-939a-ec6351eea0cc} +@mozilla.org/intl/collation;1,{aa13e4a0-a5ac-11d2-9119-006008a6edf6} +@mozilla.org/widget/transferable;1,{8b5314bc-db01-11d2-96ce-0060b0fb9956} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-16BE,{ba6151ad-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/login-manager/storage/mozStorage;1,{8c2023b9-175c-477e-9761-44ae7b549756} +@mozilla.org/network/auth-module;1?name=sys-ntlm,{bc54f001-6eb0-4e32-9f49-7e064d8e70ef} +@mozilla.org/intl/unicode/encoder;1?charset=hkscs-1,{a59da931-4091-11d5-a145-005004832142} +@mozilla.org/intl/unicode/encoder;1?charset=x-t1-cmex,{f01cb3e7-4ace-414e-a2b7-eaba03e9c86c} +@mozilla.org/satchel/form-autocomplete;1,{c11c21b2-71c9-4f87-a0f8-5e13f50495fd} +@mozilla.org/intl/unicode/decoder;1?charset=IBM852,{2d524fd1-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/network/protocol;1?name=feed,{4f91ef2e-57ba-472e-ab7a-b4999e42d6c0} +@mozilla.org/layout/contentserializer;1?mimetype=application/vnd.mozilla.xul+xml,{4aef38b7-6364-4e23-a5e7-12f837fbbd9c} +@mozilla.org/intl/unicode/encoder;1?charset=x-gbk,{ba61519b-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=IBM855,{2d524fd2-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/satchel/form-fill-controller;1,{895db6c7-dbdf-40ea-9f64-b175033243dc} +@mozilla.org/editor/texteditor;1,{e197cc01-cfe1-11d4-8eb0-87ae406dfd3f} +@mozilla.org/privatebrowsing-wrapper;1,{136e2c4d-c5a4-477c-b131-d93d7d704f64} +@mozilla.org/chrome/chrome-native-theme;1,{d930e29b-6909-44e5-ab4b-af10d6923705} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-9,{7b8556a9-ec79-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/encoder;1?charset=x-ttf-cmr,{67671792-8e25-4487-b1b7-5073cfa95fee} +@mozilla.org/nsCMSMessage;1,{a4557478-ae16-11d5-ba4b-00108303b117} +@joehewitt.com/firebug-annotation-service;1,{9589dc0d-9709-4578-883e-d393452b3611} +@mozilla.org/content/dom-selection;1,{c87a37fc-8109-4ce2-a322-8cdec925379f} +@mozilla.org/network/protocol/about;1?what=crashes,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-2022-KR,{ba61519f-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/editor/htmleditorcontroller;1,{62db0002-dbb6-43f4-8fb7-9d2538bc5747} +@mozilla.org/profile/migrator;1?app=browser&type=opera,{f34ff792-722e-4490-b195-47d242edca1c} +@mozilla.org/streamconv;1?from=multipart/x-mixed-replace&to=*/*,{7584ce90-5b25-11d3-a175-0050041caf44} +@mozilla.org/streamconv;1?from=text/ftp-dir&to=application/http-index-format,{14c0e880-623e-11d3-a178-0050041caf44} +@mozilla.org/intl/unicode/encoder;1?charset=x-mathematica5,{8a0dce80-e2f2-11d3-b32f-004005a7a7e4} +@mozilla.org/intl/unicode/encoder;1?charset=IBM864i,{2d524fdd-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/xul/xul-prototype-cache;1,{3a0a0fc1-8349-11d3-be47-00104bde6048} +@mozilla.org/intl/unicode/encoder;1?charset=UTF-16,{49b38f12-6193-11d3-b3c5-00805f8a6670} +@mozilla.org/network/default-prompt;1,{2e41ada0-62b7-4902-b9a6-e4542aa458ba} +@mozilla.org/intl/unicode/encoder;1?charset=GB2312,{379c2777-ec77-11d2-8aac-00600811a836} +@mozilla.org/security/pkiparamblock;1,{0bec75a8-1dd2-11b2-863a-f69f77c31371} +@mozilla.org/toolkit/profile-migrator;1,{4ca3c946-5408-49f0-9eca-3a97d5c67750} +@mozilla.org/network/auth-module;1?name=negotiate-gss,{96ec4163-efc8-407a-8735-007fb26be4e8} +@mozilla.org/embedding/browser/content-policy;1,{f66bc334-1dd1-11b2-bab2-90e04fe15c19} +@mozilla.org/browser/tagging-service;1,{bbc23860-2553-479d-8b78-94d9038334f7} +@mozilla.org/network/protocol/about;1?what=certerror,{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980} +@mozilla.org/js/xpc/ContextStack;1,{ff8c4d10-3194-11d3-9885-006008962422} +@mozilla.org/intl/unicode/encoder;1?charset=jis_0201,{ba615191-1dfa-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=windows-1254,{7c657d17-ec5e-11d2-8aac-00600811a836} +@mozilla.org/streamconv;1?from=uncompressed&to=rawdeflate,{461cd5dd-73c6-47a4-8cc3-603b37d84a61} +@mozilla.org/xre/app-info;1,{95d89e3e-a169-41a3-8e56-719978e15b12} +@mozilla.org/xptinfo/loader;1&type=zip,{0320e073-79c7-4dae-8055-81bed8b8db96} +@mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.audio.feed&to=*/*,{229fa115-9412-4d32-baf3-2fc407f76fb1} +@mozilla.org/intl/unicode/encoder;1?charset=KOI8-R,{6394eeb5-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/protocol/about;1?what=license,{f0acde16-1dd1-11b2-9e35-f5786fff5a66} +@mozilla.org/intl/utf8converterservice;1,{2b026890-5a2e-4981-ada2-a600358947b4} +@mozilla.org/transactionmanager;1,{9c8f9601-801a-11d2-98ba-00805f297d89} +@mozilla.org/nss_errors_service;1,{a277189c-1dd1-11b2-a8c9-e4e8bfb1338e} +@mozilla.org/saxparser/xmlreader;1,{ab1da296-6125-40ba-96d0-47a8282ae3db} +@mozilla.org/locale/posix-locale;1,{d92d57c5-ba1d-11d2-af0c-0060089fe59b} +@mozilla.org/content-dispatch-chooser;1,{e35d5067-95bc-4029-8432-e8f1e431148d} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-9,{7c657d13-ec5e-11d2-8aac-00600811a836} +@mozilla.org/network/authprompt-adapter-factory;1,{a21bfa01-f349-4394-a84c-8de5cf0737d0} +@mozilla.org/layout/plaintextsink;1,{6030f7ef-32ed-46a7-9a63-6a5d3f90445f} +@mozilla.org/gfx/region;1,{da5b130a-1dd1-11b2-ad47-f455b1814a78} +@mozilla.org/geolocation/gpsd/provider;1,{0a3be523-0f2a-32cc-ccd8-1e5986d5a79d} +@mozilla.org/network/http-authenticator;1?scheme=digest,{17491ba4-1dd2-11b2-aae3-de6b92dab620} +@mozilla.org/network/cache-service;1,{6c84aec9-29a5-4264-8fbc-bee8f922ea67} +@mozilla.org/security/entropy;1,{34587f4a-be18-43c0-9112-b782b08c0add} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-1,{920307b0-c6e8-11d2-8aa8-00600811a836} +@mozilla.org/satchel/form-history-importer;1,{db340cc2-7f50-4ea3-8427-f529daf6dc87} +@mozilla.org/spellchecker/engine;1,{56c778e4-1bee-45f3-a689-886692a97fe7} +@mozilla.org/intl/unicode/decoder;1?charset=x-euc-tw,{379c2771-ec77-11d2-8aac-00600811a836} +@mozilla.org/network/protocol/about;1?what=blank,{3decd6c8-30ef-11d3-8cd0-0060b0fc14a3} +@mozilla.org/autocomplete/search;1?name=file,{cb60980e-18a5-4a77-9110-8146614ca7f0} +@mozilla.org/autocomplete/search;1?name=places-tag-autocomplete,{1dcc23b0-d4cb-11dc-9ad6-479d56d89593} +@mozilla.org/network/protocol/about;1?what=cache-entry,{7fa5237d-b0eb-438f-9e50-ca0166e63788} +@mozilla.org/security/pk11tokendb;1,{b084a2ce-1dd1-11b2-bf10-8324f8e065cc} +@mozilla.org/network/protocol;1?name=view-source,{9c7ec5d1-23f9-11d5-aea8-8fcc0793e97f} +@mozilla.org/intl/stringcharsetdetect;1?type=ja_parallel_state_machine,{12bb8f1c-2389-11d3-b3bf-00805f8a6670} +@mozilla.org/rdf/datasource;1?name=files,{e638d760-8687-11d2-b530-000000000001} +@mozilla.org/intl/unicode/encoder;1?charset=armscii-8,{6394eebc-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-11,{9c0ff6f4-deda-40e5-806c-b6cc449c21ce} +@mozilla.org/intl/stringcharsetdetect;1?type=universal_charset_detector,{6ee5301a-3981-49bd-85f8-1a2cc228cf3e} +@mozilla.org/feed-unescapehtml;1,{10f2f5f0-f103-4901-980f-ba11bd70d60d} +@mozilla.org/dom/xpath-evaluator;1,{d0a75e02-b5e7-11d5-a7f2-df109fb8a1fc} +@mozilla.org/layout/contentserializer;1?mimetype=text/xml,{4aef38b7-6364-4e23-a5e7-12f837fbbd9c} +@mozilla.org/intl/unicode/decoder;1?charset=IBM857,{2d524fd3-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/browser/sessionstartup;1,{ec7a6c20-e081-11da-8ad9-0800200c9a66} +@mozilla.org/intl/unicode/encoder;1?charset=ISO-8859-6-I,{495eca46-0a5c-11d4-a135-005004832142} +@mozilla.org/intl/charsetdetect;1?type=universal_charset_detector,{374e0cde-f605-4259-8c92-e639c6c2eeef} +@mozilla.org/dirIndexParser;1,{a0d6ad32-1dd1-11b2-aa55-a40187b54036} +@mozilla.org/autocomplete/search;1?name=history,{d0272978-beab-4adc-a3d4-04b76acfa4e7} +@mozilla.org/network/downloader;1,{510a86bb-6019-4ed1-bb4f-965cffd23ece} +@mozilla.org/intl/unicode/decoder;1?charset=EUC-KR,{379c2775-ec77-11d2-8aac-00600811a836} +@mozilla.org/files/filereader;1,{06aa7c21-fe05-4cf2-b1c4-0c7126a4f713} +@mozilla.org/PopupWindowManager;1,{822bcd11-6432-48be-9e9d-36f7804b7747} +@mozilla.org/security/recentbadcerts;1,{e7caf8c0-3570-47fe-aa1b-da47539b5d07} +@mozilla.org/dom/json;1,{93ad72a6-02cd-4716-9626-d47d5ec275ec} +@mozilla.org/browser/feeds/result-writer;1,{49bb6593-3aff-4eb3-a068-2712c28bd58e} +@mozilla.org/intl/unicode/encoder;1?charset=x-viet-vps,{6394eec0-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/intl/unicode/encoder;1?charset=windows-1253,{7b8556ad-ec79-11d2-8aac-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-8-I,{495eca43-0a5c-11d4-a135-005004832142} +@mozilla.org/network/protocol;1?name=pcast,{1c31ed79-accd-4b94-b517-06e0c81999d5} +@mozilla.org/network/io-service;1,{9ac9e770-18bc-11d3-9337-00104ba0fd40} +@mozilla.org/uriloader/content-handler;1?type=application/x-xpinstall,{18c2f98d-b09f-11d2-bcde-00805f0e1353} +@mozilla.org/intl/unicode/decoder;1?charset=ISO-8859-1,{a3254cb0-8e20-11d2-8a98-00600811a836} +@mozilla.org/intl/unicode/decoder;1?charset=IBM864,{2d524fd5-ae74-11d3-abf7-0004aceefa51} +@mozilla.org/xul/xul-tree-builder;1,{1abdcc96-1dd2-11b2-b520-f8f59cdd67bc} +@mozilla.org/privatebrowsing;1,{c31f4883-839b-45f6-82ad-a6a9bc5ad599} +@mozilla.org/docshell/urifixup;1,{214c48a0-b57f-11d4-959c-0020183bf181} +@mozilla.org/intl/stringcharsetdetect;1?type=zh_parallel_state_machine,{fcacef21-2b40-11d3-b3bf-00805f8a6670} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-icelandic,{6394eeab-fc3d-11d2-b3b8-00805f8a6670} +@mozilla.org/network/protocol;1?name=moz-safe-about,{1423e739-782c-4081-b5d8-fe6fba68c0ef} +@mozilla.org/xul/xul-sort-service;1,{bfd05264-834c-11d2-8eac-00805f29f371} +@mozilla.org/intl/unicode/decoder;1?charset=x-mac-farsi,{6803cac8-1e3b-11d5-a145-005004832142} +@mozilla.org/image/decoder;2?type=image/x-ms-bmp,{78c61626-4d1f-4843-9364-4652d98ff6e1} +@mozilla.org/layout/htmlCopyEncoder;1,{7f915b01-98fc-11d4-8eb0-a803f80ff1bc} +@mozilla.org/intl/unicode/decoder;1?charset=UTF-32LE,{ba6151b8-1dfa-11d3-b3bf-00805f8a6670} + +[CATEGORIES] +content-sniffing-services,@mozilla.org/image/loader;1,@mozilla.org/image/loader;1 +Charset Encoders,UTF-16, +Charset Encoders,ISO-8859-8-E, +Charset Encoders,ISO-8859-4, +Charset Encoders,ISO-8859-16, +Charset Encoders,x-mac-gurmukhi, +Charset Encoders,x-ttf-cmex, +Charset Encoders,TIS-620, +Charset Encoders,ISO-IR-111, +Charset Encoders,EUC-JP, +Charset Encoders,windows-1251, +Charset Encoders,HZ-GB-2312, +Charset Encoders,x-t1-cmex, +Charset Encoders,x-mac-roman, +Charset Encoders,ISO-8859-7, +Charset Encoders,x-mac-hebrew, +Charset Encoders,ISO-8859-15, +Charset Encoders,Adobe-Symbol-Encoding, +Charset Encoders,IBM857, +Charset Encoders,x-ttf-cmsy, +Charset Encoders,x-mathematica5, +Charset Encoders,hkscs-1, +Charset Encoders,x-mac-ce, +Charset Encoders,windows-1252, +Charset Encoders,KOI8-U, +Charset Encoders,ISO-8859-10, +Charset Encoders,GB2312, +Charset Encoders,UTF-8, +Charset Encoders,x-viet-tcvn5712, +Charset Encoders,gb18030, +Charset Encoders,ISO-8859-2, +Charset Encoders,windows-1257, +Charset Encoders,x-mathematica1, +Charset Encoders,x-windows-949, +Charset Encoders,x-tamilttf-0, +Charset Encoders,ISO-8859-6-I, +Charset Encoders,ISO-8859-5, +Charset Encoders,KOI8-R, +Charset Encoders,x-imap4-modified-utf7, +Charset Encoders,VISCII, +Charset Encoders,windows-1258, +Charset Encoders,ISO-8859-8, +Charset Encoders,IBM855, +Charset Encoders,EUC-KR, +Charset Encoders,x-ttf-cmmi, +Charset Encoders,x-mathematica3, +Charset Encoders,UTF-32LE, +Charset Encoders,windows-1250, +Charset Encoders,armscii-8, +Charset Encoders,IBM864i, +Charset Encoders,IBM852, +Charset Encoders,x-euc-tw, +Charset Encoders,ISO-8859-8-I, +Charset Encoders,x-johab, +Charset Encoders,UTF-16LE, +Charset Encoders,x-user-defined, +Charset Encoders,x-mac-icelandic, +Charset Encoders,windows-874, +Charset Encoders,windows-1255, +Charset Encoders,x-mac-romanian, +Charset Encoders,x-ttf-cmr, +Charset Encoders,x-mathematica4, +Charset Encoders,ISO-8859-3, +Charset Encoders,ISO-8859-11, +Charset Encoders,Big5, +Charset Encoders,UTF-7, +Charset Encoders,Shift_JIS, +Charset Encoders,IBM866, +Charset Encoders,x-mac-devanagari, +Charset Encoders,x-mtextra, +Charset Encoders,x-mac-turkish, +Charset Encoders,x-gbk, +Charset Encoders,UTF-32BE, +Charset Encoders,x-t1-cmr, +Charset Encoders,windows-1256, +Charset Encoders,x-mac-farsi, +Charset Encoders,GEOSTD8, +Charset Encoders,UTF-32, +Charset Encoders,x-koreanjamo-0, +Charset Encoders,x-t1-cmsy, +Charset Encoders,x-mac-croatian, +Charset Encoders,UTF-16BE, +Charset Encoders,ISO-8859-6, +Charset Encoders,us-ascii, +Charset Encoders,x-mac-greek, +Charset Encoders,T.61-8bit, +Charset Encoders,ISO-8859-9, +Charset Encoders,jis_0201, +Charset Encoders,x-mac-gujarati, +Charset Encoders,ISO-8859-6-E, +Charset Encoders,x-mathematica2, +Charset Encoders,Big5-HKSCS, +Charset Encoders,windows-1253, +Charset Encoders,ISO-8859-1, +Charset Encoders,IBM864, +Charset Encoders,ISO-8859-13, +Charset Encoders,IBM850, +Charset Encoders,x-zapf-dingbats, +Charset Encoders,ISO-8859-14, +Charset Encoders,x-mac-arabic, +Charset Encoders,IBM862, +Charset Encoders,windows-936, +Charset Encoders,windows-1254, +Charset Encoders,x-t1-cmmi, +Charset Encoders,x-tscii, +Charset Encoders,ISO-2022-JP, +Charset Encoders,x-viet-vps, +Charset Encoders,x-mac-cyrillic, +net-content-sniffers,Feed Sniffer,@mozilla.org/browser/feeds/sniffer;1 +net-content-sniffers,Binary Detector,@mozilla.org/network/binary-detector;1 +JavaScript global static nameset,PrivilegeManager,@mozilla.org/security/script/nameset;1 +JavaScript global constructor,BrowserFeedWriter,@mozilla.org/browser/feeds/result-writer;1 +JavaScript global constructor,Image,@mozilla.org/content/element/html;1?name=img +JavaScript global constructor,Audio,@mozilla.org/content/element/html;1?name=audio +JavaScript global constructor,Option,@mozilla.org/content/element/html;1?name=option +agent-style-sheets,pluginproblem xbl binding,chrome://mozapps/content/plugins/pluginProblemBinding.css +agent-style-sheets,pluginfinder xbl binding,chrome://ubufox/content/alternatePluginsBinding.css +xpcom-directory-providers,spellcheck-directory-provider,@mozilla.org/spellcheck/dir-provider;1 +xpcom-directory-providers,browser-directory-provider,@mozilla.org/browser/directory-provider;1 +external-uricontentlisteners,application/x-x509-user-cert,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/x-x509-email-cert,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/x-x509-crl,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/pkix-crl,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/x-pkcs7-crl,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/x-x509-ca-cert,@mozilla.org/uriloader/psm-external-content-listener;1 +external-uricontentlisteners,application/x-x509-server-cert,@mozilla.org/uriloader/psm-external-content-listener;1 +uconv-charset-titles,chrome://global/locale/charsetTitles.properties, +pref-config-startup,ReadConfig Module,@mozilla.org/readconfig;1 +command-line-handler,x-default,@mozilla.org/browser/final-clh;1 +command-line-handler,m-privatebrowsing,@mozilla.org/privatebrowsing;1 +command-line-handler,b-jsconsole,@mozilla.org/toolkit/console-clh;1 +command-line-handler,m-setdefaultbrowser,@mozilla.org/browser/default-browser-clh;1 +command-line-handler,m-browser,@mozilla.org/browser/clh;1 +command-line-handler,y-default,@mozilla.org/toolkit/default-clh;1 +content-policy,@mozilla.org/data-document-content-policy;1,@mozilla.org/data-document-content-policy;1 +content-policy,@mozilla.org/no-data-protocol-content-policy;1,@mozilla.org/no-data-protocol-content-policy;1 +content-policy,@mozilla.org/permissions/contentblocker;1,@mozilla.org/permissions/contentblocker;1 +content-policy,@mozilla.org/embedding/browser/content-policy;1,@mozilla.org/embedding/browser/content-policy;1 +@mozilla.org/streamconv;1,?from=multipart/x-mixed-replace&to=*/*, +@mozilla.org/streamconv;1,?from=multipart/mixed&to=*/*, +@mozilla.org/streamconv;1,?from=deflate&to=uncompressed, +@mozilla.org/streamconv;1,?from=application/http-index-format&to=text/html, +@mozilla.org/streamconv;1,?from=gzip&to=uncompressed, +@mozilla.org/streamconv;1,?from=text/gopher-dir&to=application/http-index-format, +@mozilla.org/streamconv;1,?from=application/x-unknown-content-type&to=*/*, +@mozilla.org/streamconv;1,?from=text/plain&to=text/html, +@mozilla.org/streamconv;1,?from=x-compress&to=uncompressed, +@mozilla.org/streamconv;1,?from=compress&to=uncompressed, +@mozilla.org/streamconv;1,?from=application/mac-binhex40&to=*/*, +@mozilla.org/streamconv;1,?from=text/ftp-dir&to=application/http-index-format, +@mozilla.org/streamconv;1,?from=x-gzip&to=uncompressed, +@mozilla.org/streamconv;1,?from=multipart/byteranges&to=*/*, +XSLT extension functions,http://exslt.org/regular-expressions,@mozilla.org/exslt/regexp;1 +charset-detectors,cjk_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=cjk_parallel_state_machine +charset-detectors,ko_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=ko_parallel_state_machine +charset-detectors,ruprob,@mozilla.org/intl/charsetdetect;1?type=ruprob +charset-detectors,off,off +charset-detectors,universal_charset_detector,@mozilla.org/intl/charsetdetect;1?type=universal_charset_detector +charset-detectors,zhcn_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=zhcn_parallel_state_machine +charset-detectors,zhtw_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=zhtw_parallel_state_machine +charset-detectors,zh_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=zh_parallel_state_machine +charset-detectors,ja_parallel_state_machine,@mozilla.org/intl/charsetdetect;1?type=ja_parallel_state_machine +charset-detectors,ukprob,@mozilla.org/intl/charsetdetect;1?type=ukprob +JavaScript global property,InstallTrigger,@mozilla.org/xpinstall/installtrigger;1 +JavaScript global property,external,@mozilla.org/sidebar;1 +JavaScript global property,sidebar,@mozilla.org/sidebar;1 +command-line-validator,b-browser,@mozilla.org/browser/clh;1 +parser-service-category,Meta Charset Service,@mozilla.org/intl/metacharset;1 +profile-after-change,Timer Manager,@mozilla.org/updates/timer-manager;1 +profile-after-change,Extension Manager,@mozilla.org/extensions/manager;1 +Gecko-Content-Viewers,application/xml,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/x-javascript,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/javascript,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/plain,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/jpg,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/gif,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/bmp,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/x-view-source,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/icon,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/jpeg,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/pjpeg,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/ecmascript,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,mozilla.application/cached-xul,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/x-png,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/http-index-format,@mozilla.org/xpfe/http-index-format-factory-constructor +Gecko-Content-Viewers,text/rdf,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/png,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/css,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/html,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/rdf+xml,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/x-icon,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/ecmascript,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/javascript,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/xhtml+xml,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,application/vnd.mozilla.xul+xml,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,text/xml,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/vnd.microsoft.icon,@mozilla.org/content/document-loader-factory;1 +Gecko-Content-Viewers,image/x-ms-bmp,@mozilla.org/content/document-loader-factory;1 +Charset Decoders,UTF-16, +Charset Decoders,ISO-8859-8-E, +Charset Decoders,ISO-8859-4, +Charset Decoders,ISO-8859-16, +Charset Decoders,UTF-32LE, +Charset Decoders,TIS-620, +Charset Decoders,ISO-IR-111, +Charset Decoders,windows-1252, +Charset Decoders,windows-1251, +Charset Decoders,UTF-16BE, +Charset Decoders,IBM852, +Charset Decoders,x-mac-roman, +Charset Decoders,ISO-8859-7, +Charset Decoders,x-mac-ce, +Charset Decoders,ISO-8859-15, +Charset Decoders,IBM857, +Charset Decoders,gb18030, +Charset Decoders,x-viet-tcvn5712, +Charset Decoders,IBM862, +Charset Decoders,KOI8-U, +Charset Decoders,ISO-8859-2, +Charset Decoders,armscii-8, +Charset Decoders,ISO-8859-10, +Charset Decoders,UTF-8, +Charset Decoders,us-ascii, +Charset Decoders,HZ-GB-2312, +Charset Decoders,ISO-2022-JP, +Charset Decoders,x-gbk, +Charset Decoders,windows-1257, +Charset Decoders,ISO-8859-14, +Charset Decoders,x-mac-hebrew, +Charset Decoders,ISO-8859-6-I, +Charset Decoders,x-johab, +Charset Decoders,ISO-8859-5, +Charset Decoders,KOI8-R, +Charset Decoders,x-imap4-modified-utf7, +Charset Decoders,VISCII, +Charset Decoders,windows-1258, +Charset Decoders,ISO-8859-8, +Charset Decoders,EUC-KR, +Charset Decoders,x-mac-gurmukhi, +Charset Decoders,Big5, +Charset Decoders,IBM864, +Charset Decoders,windows-1250, +Charset Decoders,EUC-JP, +Charset Decoders,IBM864i, +Charset Decoders,x-euc-tw, +Charset Decoders,ISO-8859-8-I, +Charset Decoders,UTF-16LE, +Charset Decoders,x-mac-icelandic, +Charset Decoders,GB2312, +Charset Decoders,windows-1255, +Charset Decoders,x-windows-949, +Charset Decoders,ISO-2022-KR, +Charset Decoders,x-mac-romanian, +Charset Decoders,T.61-8bit, +Charset Decoders,ISO-8859-3, +Charset Decoders,ISO-8859-11, +Charset Decoders,UTF-7, +Charset Decoders,Shift_JIS, +Charset Decoders,x-mac-devanagari, +Charset Decoders,ISO-2022-CN, +Charset Decoders,UTF-32BE, +Charset Decoders,x-mac-turkish, +Charset Decoders,IBM866, +Charset Decoders,windows-1256, +Charset Decoders,x-mac-farsi, +Charset Decoders,GEOSTD8, +Charset Decoders,UTF-32, +Charset Decoders,x-mac-croatian, +Charset Decoders,ISO-8859-6, +Charset Decoders,x-mac-greek, +Charset Decoders,ISO-8859-9, +Charset Decoders,x-mac-cyrillic, +Charset Decoders,x-mac-gujarati, +Charset Decoders,ISO-8859-6-E, +Charset Decoders,Big5-HKSCS, +Charset Decoders,windows-1253, +Charset Decoders,ISO-8859-1, +Charset Decoders,ISO-8859-13, +Charset Decoders,IBM850, +Charset Decoders,x-user-defined, +Charset Decoders,x-mac-arabic, +Charset Decoders,windows-874, +Charset Decoders,windows-936, +Charset Decoders,windows-1254, +Charset Decoders,IBM855, +Charset Decoders,x-viet-vps, +geolocation-provider,Returns a geolocation from a GPSD source,@mozilla.org/geolocation/gpsd/provider;1 +JavaScript global constructor prototype alias,Image,HTMLImageElement +JavaScript global constructor prototype alias,Audio,HTMLAudioElement +JavaScript global constructor prototype alias,Option,HTMLOptionElement +module-loader,text/javascript,@mozilla.org/moz/jsloader;1 +app-startup,PrivateBrowsing Service,service,@mozilla.org/privatebrowsing;1 +app-startup,tryToClose Service,service,@mozilla.org/appshell/trytoclose;1 +app-startup,Web Content Handler Registrar,service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 +app-startup,Application,service,@mozilla.org/fuel/application;1 +app-startup,Window Data Source,service,@mozilla.org/rdf/datasource;1?name=window-mediator +app-startup,Firefox Browser Glue Service,service,@mozilla.org/browser/browserglue;1 +app-startup,Browser Session Startup Service,service,@mozilla.org/browser/sessionstartup;1 +app-startup,SystemPref Module,@mozilla.org/system-preferences;1 +app-startup,Script Security Manager,service,@mozilla.org/scriptsecuritymanager;1 +uconv-charset-data,resource://gre/res/charsetData.properties, +bookmark-observers,Used to synchronize the temporary and permanent tables of Places,@mozilla.org/places/sync;1 +JavaScript global privileged property,Application,@mozilla.org/fuel/application;1 +update-timer,Extension Manager,@mozilla.org/extensions/manager;1,getService,addon-background-update-timer,extensions.update.interval,86400 +update-timer,Microsummary Service,@mozilla.org/microsummary/service;1,getService,microsummary-generator-update-timer,browser.microsummary.generatorUpdateInterval,604800 +update-timer,Blocklist Service,@mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400 +history-observers,Used to synchronize the temporary and permanent tables of Places,@mozilla.org/places/sync;1 diff --git a/src/test/profile/selenium/firefoxprofile/content-prefs.sqlite b/src/test/profile/selenium/firefoxprofile/content-prefs.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..02d7db08894c0669f95ec9ac9160b431c1a8cee2 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/content-prefs.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/cookies.sqlite b/src/test/profile/selenium/firefoxprofile/cookies.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..efe57127b89a4f70b74c0ed32118a40a14f6d251 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/cookies.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/downloads.sqlite b/src/test/profile/selenium/firefoxprofile/downloads.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..8e56c7f894822cc4544755da71b27ec403d6ac32 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/downloads.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/extensions.cache b/src/test/profile/selenium/firefoxprofile/extensions.cache new file mode 100644 index 0000000000000000000000000000000000000000..36242d9001a508fdd3c52e30ecd506449ac94feb --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/extensions.cache @@ -0,0 +1,7 @@ +app-global langpack-en-AU@firefox-3.6.ubuntu.com rel%langpack-en-AU@firefox-3.6.ubuntu.com 1293454333 +app-global langpack-en-GB@firefox-3.6.ubuntu.com rel%langpack-en-GB@firefox-3.6.ubuntu.com 1286468210 +app-global {972ce4c6-7e08-4474-a285-3208198ce6fd} rel%{972ce4c6-7e08-4474-a285-3208198ce6fd} 1301039473 +app-global langpack-en-CA@firefox-3.6.ubuntu.com rel%langpack-en-CA@firefox-3.6.ubuntu.com 1286468210 +app-global langpack-en@firefox-3.6.ubuntu.com rel%langpack-en@firefox-3.6.ubuntu.com 1286468210 +app-system-share firebug@software.joehewitt.com rel%firebug@software.joehewitt.com 1287867233 +app-system-share ubufox@ubuntu.com rel%ubufox@ubuntu.com 1288944959 diff --git a/src/test/profile/selenium/firefoxprofile/extensions.ini b/src/test/profile/selenium/firefoxprofile/extensions.ini new file mode 100644 index 0000000000000000000000000000000000000000..b3446f0fb0abadd3b50d54eef4cdda4241fe0d23 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/extensions.ini @@ -0,0 +1,9 @@ +[ExtensionDirs] +Extension0=/usr/lib/firefox-3.6.16/extensions/langpack-en-AU@firefox-3.6.ubuntu.com +Extension1=/usr/lib/firefox-3.6.16/extensions/langpack-en-GB@firefox-3.6.ubuntu.com +Extension2=/usr/lib/firefox-3.6.16/extensions/langpack-en-CA@firefox-3.6.ubuntu.com +Extension3=/usr/lib/firefox-3.6.16/extensions/langpack-en@firefox-3.6.ubuntu.com +Extension4=/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com +Extension5=/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com +[ThemeDirs] +Extension0=/usr/lib/firefox-3.6.16/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} diff --git a/src/test/profile/selenium/firefoxprofile/extensions.rdf b/src/test/profile/selenium/firefoxprofile/extensions.rdf new file mode 100644 index 0000000000000000000000000000000000000000..439bd8d3298d5c5dac705ea55dc5cab6a0b0a170 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/extensions.rdf @@ -0,0 +1,159 @@ +<?xml version="1.0"?> +<RDF:RDF xmlns:NS1="http://www.mozilla.org/2004/em-rdf#" + xmlns:NC="http://home.netscape.com/NC-rdf#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <RDF:Description RDF:about="rdf:#$CbIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.6" + NS1:maxVersion="3.6.*" /> + <RDF:Description RDF:about="urn:mozilla:item:langpack-en@firefox-3.6.ubuntu.com" + NS1:installLocation="app-global" + NS1:version="3.6" + NS1:name="Firefox (en)" + NS1:creator="http://translations.launchpad.net"> + <NS1:type NC:parseType="Integer">8</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$CbIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="rdf:#$JbIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.6" + NS1:maxVersion="3.6.*" /> + <RDF:Description RDF:about="urn:mozilla:item:firebug@software.joehewitt.com" + NS1:installLocation="app-system-share" + NS1:version="1.5.4" + NS1:iconURL="chrome://firebug/content/firebug.png" + NS1:name="Firebug" + NS1:description="Web Development Evolved." + NS1:creator="Joe Hewitt" + NS1:homepageURL="http://www.getfirebug.com/"> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:translator>Leszek(teo)Å»yczkowski (pl-PL)</NS1:translator> + <NS1:translator>markh (nl-NL)</NS1:translator> + <NS1:translator>peter3 (sv-SE)</NS1:translator> + <NS1:translator>AlleyKat (da-DK)</NS1:translator> + <NS1:translator>Hector Zhao, lovelywcm (zh-CN)</NS1:translator> + <NS1:translator>Lukáš Kucharczyk, Michal Kec (cs-CZ)</NS1:translator> + <NS1:translator>Team erweiterungen.de, ReinekeFux, Benedikt Langens (de-DE)</NS1:translator> + <NS1:translator>l0stintranslation, gonzalopirobutirro (it-IT)</NS1:translator> + <NS1:translator>alexxed (ro-RO)</NS1:translator> + <NS1:translator>Nicolas Martin, Franck Marcia (fr-FR)</NS1:translator> + <NS1:translator>gLes (hu-HU)</NS1:translator> + <NS1:translator>Xavi Ivars - Softcatalà (ca)</NS1:translator> + <NS1:translator>gezmen (tr-TR)</NS1:translator> + <NS1:translator>eternoendless (es-AR)</NS1:translator> + <NS1:translator>Dark Preacher (ru-RU)</NS1:translator> + <NS1:translator>Tiago Oliveira, Diego de Carvalho Zimmermann, Alexandre Rapaki (pt-BR)</NS1:translator> + <NS1:translator>Juan BotÃas (es-ES)</NS1:translator> + <NS1:translator>Andriy Zhouck (uk-UA)</NS1:translator> + <NS1:translator>Hisateru Tanaka (ja-JP)</NS1:translator> + <NS1:translator>Mohsen Shadroo (fa-IR)</NS1:translator> + <NS1:translator>Eduard Babayan (hy-AM)</NS1:translator> + <NS1:translator>Helder Magalhães (pt-PT)</NS1:translator> + <NS1:translator>Tomaž MaÄus (sl-SI)</NS1:translator> + <NS1:translator>Stoyan Stefanov (bg-BG)</NS1:translator> + <NS1:translator>Kristján Bjarni Guðmundsson (is-IS)</NS1:translator> + <NS1:translator>NGUYỄN Mạnh Hùng (vi-VN)</NS1:translator> + <NS1:translator>Bwah (hr-HR)</NS1:translator> + <NS1:translator>Sonickydon (el-GR)</NS1:translator> + <NS1:contributor>John J. Barton (IBM Almaden)</NS1:contributor> + <NS1:contributor>Jan Odvarko (Mozilla Corp.)</NS1:contributor> + <NS1:contributor>Max Stepanov (Aptana Inc.)</NS1:contributor> + <NS1:contributor>Rob Campbell (Mozilla Corp.)</NS1:contributor> + <NS1:contributor>Hans Hillen (Paciello Group, Mozilla)</NS1:contributor> + <NS1:contributor>Curtis Bartley (Mozilla Corp.)</NS1:contributor> + <NS1:contributor>Mike Collins (IBM Almaden)</NS1:contributor> + <NS1:contributor>Kevin Decker</NS1:contributor> + <NS1:contributor>Mike Ratcliffe (Comartis AG)</NS1:contributor> + <NS1:contributor>Hernan RodrÃguez Colmeiro</NS1:contributor> + <NS1:contributor>Austin Andrews</NS1:contributor> + <NS1:contributor>Christoph Dorn</NS1:contributor> + <NS1:contributor>Steven Roussey (AppCenter Inc, Network54)</NS1:contributor> + <NS1:targetApplication RDF:resource="rdf:#$ubIeH3"/> + <NS1:targetApplication RDF:resource="rdf:#$vbIeH3"/> + </RDF:Description> + <RDF:Seq RDF:about="urn:mozilla:item:root"> + <RDF:li RDF:resource="urn:mozilla:item:langpack-en-AU@firefox-3.6.ubuntu.com"/> + <RDF:li RDF:resource="urn:mozilla:item:langpack-en-GB@firefox-3.6.ubuntu.com"/> + <RDF:li RDF:resource="urn:mozilla:item:{972ce4c6-7e08-4474-a285-3208198ce6fd}"/> + <RDF:li RDF:resource="urn:mozilla:item:langpack-en-CA@firefox-3.6.ubuntu.com"/> + <RDF:li RDF:resource="urn:mozilla:item:langpack-en@firefox-3.6.ubuntu.com"/> + <RDF:li RDF:resource="urn:mozilla:item:firebug@software.joehewitt.com"/> + <RDF:li RDF:resource="urn:mozilla:item:ubufox@ubuntu.com"/> + </RDF:Seq> + <RDF:Description RDF:about="urn:mozilla:item:langpack-en-CA@firefox-3.6.ubuntu.com" + NS1:installLocation="app-global" + NS1:version="3.6" + NS1:name="Firefox (en-CA)" + NS1:creator="http://translations.launchpad.net"> + <NS1:type NC:parseType="Integer">8</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$JbIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:langpack-en-GB@firefox-3.6.ubuntu.com" + NS1:installLocation="app-global" + NS1:version="3.6" + NS1:name="Firefox (en-GB)" + NS1:creator="http://translations.launchpad.net"> + <NS1:type NC:parseType="Integer">8</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$3cIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="rdf:#$3cIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.6" + NS1:maxVersion="3.6.*" /> + <RDF:Description RDF:about="rdf:#$yaIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="1.5" + NS1:maxVersion="3.7.*" /> + <RDF:Description RDF:about="rdf:#$acIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.6" + NS1:maxVersion="3.6.*" /> + <RDF:Description RDF:about="urn:mozilla:item:langpack-en-AU@firefox-3.6.ubuntu.com" + NS1:installLocation="app-global" + NS1:version="3.6" + NS1:name="Firefox (en-AU)" + NS1:creator="http://translations.launchpad.net"> + <NS1:type NC:parseType="Integer">8</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$acIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="rdf:#$vbIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.5" + NS1:maxVersion="3.6.*" /> + <RDF:Description RDF:about="urn:mozilla:item:ubufox@ubuntu.com" + NS1:installLocation="app-system-share" + NS1:version="0.9rc2" + NS1:iconURL="chrome://ubufox/content/ubuntulogo32.png" + NS1:name="Ubuntu Firefox Modifications" + NS1:description="Ubuntu configuration defaults and apt support for firefox extensions/plugins." + NS1:creator="Canonical Ltd."> + <NS1:type NC:parseType="Integer">2</NS1:type> + <NS1:contributor>Alexander Sack <asac@ubuntu.com></NS1:contributor> + <NS1:contributor>Sasa Bodiroza <jazzva@gmail.com></NS1:contributor> + <NS1:contributor>Daniel Abramov <ex@vingrad.ru></NS1:contributor> + <NS1:contributor>Arzhel Younsi <xionox@gmail.com></NS1:contributor> + <NS1:contributor>Saïvann Carignan <oxmosys@gmail.com></NS1:contributor> + <NS1:targetApplication RDF:resource="rdf:#$yaIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mozilla:item:{972ce4c6-7e08-4474-a285-3208198ce6fd}" + NS1:installLocation="app-global" + NS1:version="3.6.16" + NS1:internalName="classic/1.0" + NS1:locked="true" + NS1:appManaged="true" + NS1:name="Default" + NS1:description="The default theme." + NS1:creator="Mozilla" + NS1:contributor="Mozilla Contributors"> + <NS1:type NC:parseType="Integer">4</NS1:type> + <NS1:targetApplication RDF:resource="rdf:#$YbIeH3"/> + </RDF:Description> + <RDF:Description RDF:about="rdf:#$YbIeH3" + NS1:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" + NS1:minVersion="3.6.16" + NS1:maxVersion="3.6.16" /> + <RDF:Description RDF:about="rdf:#$ubIeH3" + NS1:id="toolkit@mozilla.org" + NS1:minVersion="1.9.1" + NS1:maxVersion="1.9.2.*" /> +</RDF:RDF> diff --git a/src/test/profile/selenium/firefoxprofile/firebug/annotations.json b/src/test/profile/selenium/firefoxprofile/firebug/annotations.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/firebug/annotations.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/test/profile/selenium/firefoxprofile/formhistory.sqlite b/src/test/profile/selenium/firefoxprofile/formhistory.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..01dcc49ab9a9b3f89879a7adfb07384f04799207 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/formhistory.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/key3.db b/src/test/profile/selenium/firefoxprofile/key3.db new file mode 100644 index 0000000000000000000000000000000000000000..79c9765ee2584fb7bef3b2132e2ddceb72d7b405 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/key3.db differ diff --git a/src/test/profile/selenium/firefoxprofile/localstore.rdf b/src/test/profile/selenium/firefoxprofile/localstore.rdf new file mode 100644 index 0000000000000000000000000000000000000000..fabd80a26f72cbc461bfd589eb2c1e26efff125d --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/localstore.rdf @@ -0,0 +1,66 @@ +<?xml version="1.0"?> +<RDF:RDF xmlns:NC="http://home.netscape.com/NC-rdf#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <RDF:Description RDF:about="chrome://browser/content/preferences/connection.xul"> + <NC:persist RDF:resource="chrome://browser/content/preferences/connection.xul#ConnectionsDialog"/> + </RDF:Description> + <RDF:Description RDF:about="chrome://browser/content/preferences/connection.xul#ConnectionsDialog" + screenX="62" + screenY="44" /> + <RDF:Description RDF:about="chrome://browser/content/preferences/preferences.xul#BrowserPreferences" + screenX="184" + screenY="201" + lastSelected="paneAdvanced" /> + <RDF:Description RDF:about="chrome://browser/content/preferences/preferences.xul"> + <NC:persist RDF:resource="chrome://browser/content/preferences/preferences.xul#BrowserPreferences"/> + </RDF:Description> + <RDF:Description RDF:about="chrome://global/content/customizeToolbar.xul#CustomizeToolbarWindow" + width="636" + height="400" /> + <RDF:Description RDF:about="chrome://global/content/customizeToolbar.xul"> + <NC:persist RDF:resource="chrome://global/content/customizeToolbar.xul#CustomizeToolbarWindow"/> + </RDF:Description> + <RDF:Description RDF:about="chrome://browser/content/preferences/securityWarnings.xul"> + <NC:persist RDF:resource="chrome://browser/content/preferences/securityWarnings.xul#SecurityWarnings"/> + </RDF:Description> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#sidebar-box" + sidebarcommand="" + width="" + src="" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#navigator-toolbox" + iconsize="small" + mode="text" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#nav-bar" + currentset="unified-back-forward-button,back-button,forward-button,reload-button,stop-button,home-button,urlbar-container" + iconsize="small" + mode="text" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#toolbar-menubar" + currentset="menubar-items" + iconsize="small" + mode="text" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#PersonalToolbar" + collapsed="true" + currentset="personal-bookmarks" + iconsize="small" + mode="text" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#main-window" + width="820" + height="956" + sizemode="normal" + screenY="32" + screenX="858" /> + <RDF:Description RDF:about="chrome://browser/content/preferences/securityWarnings.xul#SecurityWarnings" + screenX="25" + screenY="197" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul#sidebar-title" + value="" /> + <RDF:Description RDF:about="chrome://browser/content/browser.xul"> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#main-window"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#PersonalToolbar"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#toolbar-menubar"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#nav-bar"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#navigator-toolbox"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#sidebar-box"/> + <NC:persist RDF:resource="chrome://browser/content/browser.xul#sidebar-title"/> + </RDF:Description> +</RDF:RDF> diff --git a/src/test/profile/selenium/firefoxprofile/mimeTypes.rdf b/src/test/profile/selenium/firefoxprofile/mimeTypes.rdf new file mode 100644 index 0000000000000000000000000000000000000000..1540e39d91c69fb718c6ff0ea65a1f42975979f5 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/mimeTypes.rdf @@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<RDF:RDF xmlns:NC="http://home.netscape.com/NC-rdf#" + xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <RDF:Description RDF:about="urn:scheme:handler:webcal" + NC:useSystemDefault="true" + NC:alwaysAsk="true"> + <NC:possibleApplication RDF:resource="urn:handler:web:http://30boxes.com/external/widget?refer=ff&url=%s"/> + </RDF:Description> + <RDF:Description RDF:about="urn:mimetypes"> + <NC:MIME-types RDF:resource="urn:mimetypes:root"/> + </RDF:Description> + <RDF:Description RDF:about="urn:handler:web:https://www.mibbit.com/?url=%s" + NC:prettyName="Mibbit" + NC:uriTemplate="https://www.mibbit.com/?url=%s" /> + <RDF:Description RDF:about="urn:scheme:handler:mailto" + NC:useSystemDefault="true" + NC:alwaysAsk="false"> + <NC:possibleApplication RDF:resource="urn:handler:web:https://mail.google.com/mail/?extsrc=mailto&url=%s"/> + <NC:possibleApplication RDF:resource="urn:handler:web:http://compose.mail.yahoo.com/?To=%s"/> + </RDF:Description> + <RDF:Description RDF:about="urn:scheme:webcal" + NC:value="webcal"> + <NC:handlerProp RDF:resource="urn:scheme:handler:webcal"/> + </RDF:Description> + <RDF:Description RDF:about="urn:handler:web:http://compose.mail.yahoo.com/?To=%s" + NC:prettyName="Yahoo! Mail" + NC:uriTemplate="http://compose.mail.yahoo.com/?To=%s" /> + <RDF:Description RDF:about="urn:root" + NC:en-US_defaultHandlersVersion="3" /> + <RDF:Description RDF:about="urn:scheme:handler:irc" + NC:alwaysAsk="true"> + <NC:possibleApplication RDF:resource="urn:handler:web:https://www.mibbit.com/?url=%s"/> + </RDF:Description> + <RDF:Seq RDF:about="urn:schemes:root"> + <RDF:li RDF:resource="urn:scheme:mailto"/> + <RDF:li RDF:resource="urn:scheme:irc"/> + <RDF:li RDF:resource="urn:scheme:ircs"/> + <RDF:li RDF:resource="urn:scheme:webcal"/> + </RDF:Seq> + <RDF:Description RDF:about="urn:scheme:mailto" + NC:value="mailto"> + <NC:handlerProp RDF:resource="urn:scheme:handler:mailto"/> + </RDF:Description> + <RDF:Description RDF:about="urn:handler:web:http://30boxes.com/external/widget?refer=ff&url=%s" + NC:prettyName="30 Boxes" + NC:uriTemplate="http://30boxes.com/external/widget?refer=ff&url=%s" /> + <RDF:Seq RDF:about="urn:mimetypes:root"> + </RDF:Seq> + <RDF:Description RDF:about="urn:handler:web:https://mail.google.com/mail/?extsrc=mailto&url=%s" + NC:prettyName="Gmail" + NC:uriTemplate="https://mail.google.com/mail/?extsrc=mailto&url=%s" /> + <RDF:Description RDF:about="urn:scheme:handler:ircs" + NC:alwaysAsk="true"> + <NC:possibleApplication RDF:resource="urn:handler:web:https://www.mibbit.com/?url=%s"/> + </RDF:Description> + <RDF:Description RDF:about="urn:scheme:ircs" + NC:value="ircs"> + <NC:handlerProp RDF:resource="urn:scheme:handler:ircs"/> + </RDF:Description> + <RDF:Description RDF:about="urn:scheme:irc" + NC:value="irc"> + <NC:handlerProp RDF:resource="urn:scheme:handler:irc"/> + </RDF:Description> + <RDF:Description RDF:about="urn:schemes"> + <NC:Protocol-Schemes RDF:resource="urn:schemes:root"/> + </RDF:Description> +</RDF:RDF> diff --git a/src/test/profile/selenium/firefoxprofile/permissions.sqlite b/src/test/profile/selenium/firefoxprofile/permissions.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..f2069bd4a863807e8dff6d59012d6e04578a82e7 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/permissions.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/places.sqlite b/src/test/profile/selenium/firefoxprofile/places.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..4925ab71261cab51343b04231285fdd596b11c4e Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/places.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/places.sqlite-journal b/src/test/profile/selenium/firefoxprofile/places.sqlite-journal new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/profile/selenium/firefoxprofile/pluginreg.dat b/src/test/profile/selenium/firefoxprofile/pluginreg.dat new file mode 100644 index 0000000000000000000000000000000000000000..e9a251c90a75fbd0c3cc1084720ae8b4f2e1a45d --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/pluginreg.dat @@ -0,0 +1,90 @@ +Generated File. Do not edit. + +[HEADER] +Version:0.11:$ + +[PLUGINS] +libflashplayer.so:$ +/usr/lib/flashplugin-installer/libflashplayer.so:$ +:$ +1303032985000:1:5:$ +Shockwave Flash 10.2 r159:$ +Shockwave Flash:$ +2 +0:application/x-shockwave-flash:Shockwave Flash:swf:$ +1:application/futuresplash:FutureSplash Player:spl:$ +librhythmbox-itms-detection-plugin.so:$ +/usr/lib/mozilla/plugins/librhythmbox-itms-detection-plugin.so:$ +:$ +1295949257000:1:5:$ +This plug-in detects the presence of iTunes when opening iTunes Store URLs in a web page with Firefox.:$ +iTunes Application Detector:$ +1 +0:application/itunes-plugin:::$ +libtotem-narrowspace-plugin.so:$ +/usr/lib/mozilla/plugins/libtotem-narrowspace-plugin.so:$ +:$ +1285633033000:1:5:$ +The <a href="http://www.gnome.org/projects/totem/">Totem</a> 2.32.0 plugin handles video and audio streams.:$ +QuickTime Plug-in 7.6.6:$ +5 +0:video/quicktime:QuickTime video:mov:$ +1:video/mp4:MPEG-4 video:mp4:$ +2:image/x-macpaint:MacPaint Bitmap image:pntg:$ +3:image/x-quicktime:Macintosh Quickdraw/PICT drawing:pict, pict1, pict2:$ +4:video/x-m4v:MPEG-4 video:m4v:$ +libtotem-mully-plugin.so:$ +/usr/lib/mozilla/plugins/libtotem-mully-plugin.so:$ +:$ +1285633033000:1:5:$ +DivX Web Player version 1.4.0.233:$ +DivX® Web Player:$ +1 +0:video/divx:AVI video:divx:$ +libtotem-gmp-plugin.so:$ +/usr/lib/mozilla/plugins/libtotem-gmp-plugin.so:$ +:$ +1285633033000:1:5:$ +The <a href="http://www.gnome.org/projects/totem/">Totem</a> 2.32.0 plugin handles video and audio streams.:$ +Windows Media Player Plug-in 10 (compatible; Totem):$ +13 +0:application/x-mplayer2:AVI video:avi, wma, wmv:$ +1:video/x-ms-asf-plugin:ASF video:asf, wmv:$ +2:video/x-msvideo:AVI video:asf, wmv:$ +3:video/x-ms-asf:ASF video:asf:$ +4:video/x-ms-wmv:Windows Media video:wmv:$ +5:video/x-wmv:Windows Media video:wmv:$ +6:video/x-ms-wvx:Windows Media video:wmv:$ +7:video/x-ms-wm:Windows Media video:wmv:$ +8:video/x-ms-wmp:Windows Media video:wmv:$ +9:application/x-ms-wms:Windows Media video:wms:$ +10:application/x-ms-wmp:Windows Media video:wmp:$ +11:application/asx:Microsoft ASX playlist:asx:$ +12:audio/x-ms-wma:Windows Media audio:wma:$ +libtotem-cone-plugin.so:$ +/usr/lib/mozilla/plugins/libtotem-cone-plugin.so:$ +:$ +1285633033000:1:5:$ +The <a href="http://www.gnome.org/projects/totem/">Totem</a> 2.32.0 plugin handles video and audio streams.:$ +VLC Multimedia Plugin (compatible Totem 2.32.0):$ +20 +0:application/x-vlc-plugin:VLC Multimedia Plugin::$ +1:application/vlc:VLC Multimedia Plugin::$ +2:video/x-google-vlc-plugin:VLC Multimedia Plugin::$ +3:application/x-ogg:Ogg multimedia file:ogg:$ +4:application/ogg:Ogg multimedia file:ogg:$ +5:audio/ogg:Ogg Audio:oga:$ +6:audio/x-ogg:Ogg Audio:ogg:$ +7:video/ogg:Ogg Video:ogv:$ +8:video/x-ogg:Ogg Video:ogg:$ +9:application/annodex:Annodex exchange format:anx:$ +10:audio/annodex:Annodex Audio:axa:$ +11:video/annodex:Annodex Video:axv:$ +12:video/mpeg:MPEG video:mpg, mpeg, mpe:$ +13:audio/wav:WAV audio:wav:$ +14:audio/x-wav:WAV audio:wav:$ +15:audio/mpeg:MP3 audio:mp3:$ +16:application/x-nsv-vp3-mp3:NullSoft video:nsv:$ +17:video/flv:Flash video:flv:$ +18:video/webm:WebM video:webm:$ +19:application/x-totem-plugin:Totem Multimedia plugin::$ diff --git a/src/test/profile/selenium/firefoxprofile/prefs.js b/src/test/profile/selenium/firefoxprofile/prefs.js new file mode 100644 index 0000000000000000000000000000000000000000..91fdd76b006bbb33a310d9ef3b5b777b0d21bbc7 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/prefs.js @@ -0,0 +1,48 @@ +# Mozilla User Preferences + +/* Do not edit this file. + * + * If you make changes to this file while the application is running, + * the changes will be overwritten when the application exits. + * + * To make a manual change to preferences, you can visit the URL about:config + * For more information, see http://www.mozilla.org/unix/customizing.html#prefs + */ + +user_pref("app.update.lastUpdateTime.places-maintenance-timer", 1304093622); +user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1304093594); +user_pref("browser.bookmarks.restore_default_bookmarks", false); +user_pref("browser.download.manager.showWhenStarting", false); +user_pref("browser.history_expire_days.mirror", 180); +user_pref("browser.migration.version", 1); +user_pref("browser.offline", false); +user_pref("browser.offline-apps.notify", false); +user_pref("browser.places.smartBookmarksVersion", 2); +user_pref("browser.preferences.advanced.selectedTabIndex", 3); +user_pref("browser.privatebrowsing.autostart", true); +user_pref("browser.safebrowsing.enabled", false); +user_pref("browser.safebrowsing.malware.enabled", false); +user_pref("browser.search.update", false); +user_pref("browser.sessionstore.resume_session_once", true); +user_pref("browser.startup.homepage", "about:blank"); +user_pref("browser.startup.homepage_override.mstone", "rv:1.9.2.16"); +user_pref("browser.startup.page", 0); +user_pref("browser.tabs.warnOnClose", false); +user_pref("browser.tabs.warnOnOpen", false); +user_pref("distribution.canonical.bookmarksProcessed", true); +user_pref("dom.disable_open_during_load", false); +user_pref("extensions.enabledItems", "langpack-en-AU@firefox-3.6.ubuntu.com:3.6,langpack-en-GB@firefox-3.6.ubuntu.com:3.6,langpack-en-CA@firefox-3.6.ubuntu.com:3.6,langpack-en@firefox-3.6.ubuntu.com:3.6,firebug@software.joehewitt.com:1.5.4,ubufox@ubuntu.com:0.9rc2,{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.6.16"); +user_pref("extensions.lastAppVersion", "3.6.16"); +user_pref("extensions.update.enabled", false); +user_pref("general.warnOnAboutConfig", false); +user_pref("intl.charsetmenu.browser.cache", "UTF-8"); +user_pref("layout.spellcheckDefault", 0); +user_pref("network.cookie.prefsMigrated", true); +user_pref("network.online", false); +user_pref("privacy.sanitize.migrateFx3Prefs", true); +user_pref("security.warn_entering_weak", false); +user_pref("security.warn_viewing_mixed", false); +user_pref("signon.rememberSignons", false); +user_pref("toolkit.networkmanager.disable", true); +user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1306685517); +user_pref("xpinstall.whitelist.required", false); diff --git a/src/test/profile/selenium/firefoxprofile/search.json b/src/test/profile/selenium/firefoxprofile/search.json new file mode 100644 index 0000000000000000000000000000000000000000..c2f796f4b3b9f27817c2e5f718eda14588c4adff --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/search.json @@ -0,0 +1 @@ +{"version":6,"buildID":"20110323142937","locale":"en-US","directories":{"/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/searchplugins":{"lastModifiedTime":1288944959000,"engines":[{"_id":"/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/searchplugins/ask.xml","_name":"Ask.com","description":"Ask.com Search Engine - Better Web Search","__searchForm":"http://www.ask.com/","_iconURL":"data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAACbm5sAAADJAAAA1gAAANMAAADYAAAAyACcnJ0AAADLAAEBywDCwsAAjIy2AH9/gwBdXa4AAAC5AAAAygAwMOEAMjLgADMzvQAEBHwAaGipAAAAzwCtsLEAhYWgAAsLygDq6toAQkK3AGZnigA5O84ACAiuANjY3wAICIsAAADAAGVljgAEBIQAAADfAGNiegAREZAAwsLzAAcHkwAEBZ0Ag4jOAC0twAALC7QAqK7dAKSq1wBycqQABATQAPT04ACYm74ARkaOALO09wAmJnQAJSXJADw9fwAzNc4ALzDCAHp6pACdnZkApKevAL29sQD5+foAkpKcAOzs4AAMDMoAPj7iAKGinACvr6oAT0/wAAwNyQAAANIAlJTaAN/f0QCcnZ0AAADRAF5erQAAAJ8AAADDAAAAzAA1NrwAMTGfAAkJ1QAAAMQAWlqvAHJ31wDMzMAAFhbHAAAAiQBERNIA8fHmAAgI1gCys6oAu7v4AD09ngDDwfoABgbOAM7N9wCYmPUAKyuOABkZmgAyMsEAiYq8AHp68gDDw5sAAgLPALW2rwCdnZgAAAC9AAMD1wCenpgA9fX1AAAArQCCgrIA0dLYAK+vnwB3e9kA5ubSAOfn+AClp6cA3NzDAMHHygBQU9MABATCAG5z2gAcHMQAio/aAAAA2QD19fwAnaHIAIaGogDm5uoAk5N0AK+ytAAMDNUAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////////////////////////+DBgAAAAAASBX///////8GEzQ/Ll5VEUo9aXX///86e08hAg1qUUUiaymAOXf/NxQlglZvIzgzHksFeQxs/xcBEG1aWC1lc2YgCmEEUkE2BwFdaHAkQ3RGRxgqAmcWKwgFD1Q7Yn4xYzx2En0DGf9TBwFbLyZgCVwdQgtuBE7//3xEQD4nA1BZgTVXHwIw/////3pkHEkOTV8aTIR//////////yxyeBsycSj/////////////////////////////////////////////////AAD//wAA//8AAMAfAACABwAAAAEAAAABAAAAAAAAAAAAAAAAAACAAAAAwAAAAPABAAD8BwAA//8AAP//AAA=","_urls":[{"template":"http://www.ask.com/web","rels":[],"params":[{"name":"q","value":"{searchTerms}"},{"name":"o","value":"1576"},{"name":"l","value":"dis"}]}],"filePath":"/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/searchplugins/ask.xml","_installLocation":3,"queryCharset":"UTF-8"}]},"/usr/lib/firefox-addons/searchplugins/en-US":{"lastModifiedTime":1301039473000,"engines":[{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/eBay.xml","_name":"eBay","description":"eBay - Online auctions","__searchForm":"http://search.ebay.com/","_iconURL":"data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAADAAAAA/wAAAABAAABAQAAAgEAAAMBAAAD/QAAAAIAAAECAAACAgAAAwIAAAP+AAAAAwAAAQMAAAIDAAADAwAAA/8AAAAD/AABA/wAAgP8AAMD/AAD//wAAAABAAEAAQACAAEAAwABAAP8AQAAAQEAAQEBAAIBAQADAQEAA/0BAAACAQABAgEAAgIBAAMCAQAD/gEAAAMBAAEDAQACAwEAAwMBAAP/AQAAA/0AAQP9AAID/QADA/0AA//9AAAAAgABAAIAAgACAAMAAgAD/AIAAAECAAEBAgACAQIAAwECAAP9AgAAAgIAAQICAAICAgADAgIAA/4CAAADAgABAwIAAgMCAAMDAgAD/wIAAAP+AAED/gACA/4AAwP+AAP//gAAAAMAAQADAAIAAwADAAMAA/wDAAABAwABAQMAAgEDAAMBAwAD/QMAAAIDAAECAwACAgMAAwIDAAP+AwAAAwMAAQMDAAIDAwADAwMAA/8DAAAD/wABA/8AAgP/AAMD/wAD//8AAAAD/AEAA/wCAAP8AwAD/AP8A/wAAQP8AQED/AIBA/wDAQP8A/0D/AACA/wBAgP8AgID/AMCA/wD/gP8AAMD/AEDA/wCAwP8AwMD/AP/A/wAA//8AQP//AID//wDA//8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8fHx8fHx8fHx8fHx8AAB8cGRkUFAcHBx8fBUKfAAAfFBkfHxNHF4cb29vCnwAAHxkZFBQUBx8HG98bwp8fAB8ZGR8UGQcXhxvb28KFXx8fHZkZGRNHBwcfG8jCgoQfAB8fHx8HBx8b29vCnwPCnwAAAB8fBwcfHx8EBB8Dwp8AAAAAHx8fHwAfHx8AHx8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA//8AAP//AACAAwAAAAMAAAADAAAAAQAAAAAAAAAAAACAAAAA4AAAAPCIAAD//wAA//8AAP//AAA=","_urls":[{"template":"http://rover.ebay.com/rover/1/711-47294-18009-3/4","rels":[],"params":[{"name":"satitle","value":"{searchTerms}"}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/eBay.xml","_installLocation":3},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/google.xml","_name":"Google","description":"Google Search","__searchForm":"http://www.google.com/firefox","_iconURL":"data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA","_urls":[{"template":"http://suggestqueries.google.com/complete/search?output=firefox&client=firefox&hl={moz:locale}&q={searchTerms}","rels":[],"type":"application/x-suggestions+json","params":[]},{"template":"http://www.google.com/search","rels":[],"params":[{"name":"client","value":"ubuntu"},{"name":"channel","value":"fs"},{"name":"q","value":"{searchTerms}"},{"name":"ie","value":"utf-8"},{"name":"oe","value":"utf-8"}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/google.xml","_installLocation":3,"queryCharset":"UTF-8"},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/yahoo.xml","_name":"Yahoo","description":"Yahoo Search","__searchForm":"http://search.yahoo.com/","_iconURL":"data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbgJqAIoCdgCaAnoAnhKCAKYijgCuLpIAskKeALpSpgC+Yq4AzHy8ANqezgDmvt4A7tLqAPz5+wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlRFIoABWAKERERE6ADcKMzzu2hOgAAhERK8REWCWBERE36ERMHMEREvo6iEgY6hEn6Pu0mAzqkz/xjMzoDNwpERERDoAMzAKlERIoAAzMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//AADAOQAAgBkAAAAPAAAACQAAAAkAAAAIAAAACAAAAAgAAIAYAADAOAAA//8AAP//AAD//wAA","_urls":[{"template":"http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}","rels":[],"type":"application/x-suggestions+json","params":[]},{"template":"http://search.yahoo.com/search","rels":[],"params":[{"name":"p","value":"{searchTerms}"},{"name":"ei","value":"UTF-8"},{"pref":"yahoo-fr","name":"fr","condition":"pref","mozparam":true}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/yahoo.xml","_installLocation":3,"queryCharset":"UTF-8"},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/amazondotcom.xml","_name":"Amazon.com","description":"Amazon.com Search","__searchForm":"http://www.amazon.com/","_iconURL":"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHgSURBVHjalFM9TNtQEP4cB7PwM1RITUXIgsRaYEEVEyKZwhiyZAQyd0BhpFOlIjoBqhjSqVQMoVMLLAjEwECCQJkSkBqJYDOAFOMKFSf28d7DTUxiUDnp/Pzeu/vuu7t3ICKF6SLTMv2/lB0fRWKfjwDm4JJisYh0Oo3fpZLYT0SjSCQS8JAFMADNDZ3NZsnf1taiqVTKi4nGASruk5lkkmTmMB6JUKFQqO+DfX1eABWeQoVR6f7HSdM0obqu48Yw8G1tDT82NsRd1TSbU9BbGPCog8PDj+jLzurFoAVgMh4XxoNDQ6SqKi0tL9eBvAB8zZwymYxYY7EYAoEA8vm82BNTg6XUIs0MeGTZoR1mhXSnwNl4pmAbjU7mcjkKhkL1ynMnntZ4OEw3VyrV8utk7s5TdW++0QXz+1i3P7IK36t+PCfVn1OQOoOA0gXr5DPak+cPXbBK+/T3S69AtY3LJ98vZ1or/iLr+pTuvr59/A6s003UdqZFJF/PCKQ3o5CUznoBST2AfbEF/9iqYEDaIfwj73VJPEfgNTe0tWNYR0uwy9uOW0OkrgHI7z5ADo2C7v48nLV3XHKAT+x/1m1sX58xsBxg8rZJrDYD8DHHp4aJj/MK09sXjPOt46PcCzAACXY8/u34wN0AAAAASUVORK5CYII=","_urls":[{"template":"http://www.amazon.com/exec/obidos/external-search/","rels":[],"params":[{"name":"field-keywords","value":"{searchTerms}"},{"name":"mode","value":"blended"},{"name":"tag","value":"wwwcanoniccom-20"},{"name":"sourceid","value":"Mozilla-search"}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/amazondotcom.xml","_installLocation":3},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/creativecommons.xml","_name":"Creative Commons","description":"Find photos, movies, music, and text to rip, sample, mash, and share.","__searchForm":"http://search.creativecommons.org/","_iconURL":"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAJUSURBVDiNjZO9S1thGMXPvTfJFbnkipNkLLS0ksFg0M0lf4CboNCEgIIg/RiKtEOn0qGWTtbVoBYcIji10I9J0ApWCjp0kRaXdhHjTW4+uGnur4NJ8GOwZ3nf4TnnfZ5z3scAdBGGYdyVdN+yrGHTNNOtVqsVhuG+pO+S3gE/LtV3BIxzPDJNc8FxHGN0dNRKpVIGoJ2dndr+/r5Vr9cl6bmkN0AoSQIEyHXdj5KYnZ3F932uolKpkM/nK5KQ9FmSCZwLOI7zQBLr6+vXiFdRLBaDtsiTTve3YrFYkM/nbyR3MDU1dSKpLumO+vr6Xruui+d5AFSrVVZWVtjY2KDRaABwdHTE4uIie3t7AJTLZaLRaFXSCyUSid1MJgOA53n09/eTTqdJJpPMzc2xurqKbduMj48Tj8fZ3d0FYHBw8FjSezmOU56fnwdgeXkZ27ap1WpUKhWazSZjY2Nks1kASqVSd4zp6eljSX/MtiHdRDpnEATyfb+bkiSVSqXu3TCM8xgHBga+dkY4OzvDdV2GhoZIJBLMzMxQKBSIRqNkMhlisRhbW1sAJJPJn5I+KB6Pv7poou/7rK2tsbm5SRAEXROXlpY4ODgAoFarYdu2J+llN8ZcLvffMeZyud+SGpLuCVBPT89jSRQKhRvJxWKxISmU9JTOT5Rk9Pb2fpHE5OQkJycn14inp6dMTEx4bdM/SbKAy8sk6WEkElmwLCuSSqUYGRmxgHB7e7t+eHgYazabgaRnkt7SeZnr63xbUtYwjGHTNNNhGP4F9iR9a6/zr4v1/wDE1D9XlC4rrAAAAABJRU5ErkJggg==","_urls":[{"template":"http://search.creativecommons.org/","rels":[],"params":[{"name":"q","value":"{searchTerms}"},{"name":"sourceid","value":"Mozilla-search"}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/creativecommons.xml","_installLocation":3,"queryCharset":"UTF-8"},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/wikipedia.xml","_name":"Wikipedia (en)","description":"Wikipedia, the free encyclopedia","__searchForm":"http://en.wikipedia.org/wiki/Special:Search","_iconURL":"data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","_urls":[{"template":"http://en.wikipedia.org/w/api.php","rels":[],"type":"application/x-suggestions+json","params":[{"name":"action","value":"opensearch"},{"name":"search","value":"{searchTerms}"}]},{"template":"http://en.wikipedia.org/wiki/Special:Search","rels":[],"params":[{"name":"search","value":"{searchTerms}"},{"name":"sourceid","value":"Mozilla-search"}]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/wikipedia.xml","_installLocation":3,"queryCharset":"UTF-8"},{"_id":"/usr/lib/firefox-addons/searchplugins/en-US/answers.xml","_name":"Answers.com","description":"Dictionary Search on Answers.com","__searchForm":"http://www.answers.com/","_iconURL":"data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////K////4f////E////5f///+n////P////mv///0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8E////fv///+//////////////////////7NnP/+LFtv/////+////of///xYAAAAAAAAAAAAAAAD///8D////lf////////////j0//bi1v/OlXf/tGU9/6FCEv/OmH3////////////////D////FgAAAAAAAAAA////avPm4P/evaz/8NbI//7r3//23M3/xYRi/5kzAP/Df1z//u/l//749P/v4dn/+PPw/////6j///8B////GP///+W/f1//smM7//bczf/+69///uvf/9ytlP+ZMwD/5se3/+/f1//AgmP/nj0N/927qv/////+////QP///2z/////8NvQ/8WCYP/+69///uvf//7r3/+7ckz/pUkb/9m1ov+ePQ3/okUW/8+fh//38O3//////////5r///+t//////7y6v/Cflv/58Cr//DRwP/mwKv/okQU/8ODYv/cuqj/yZN4//Tq5f/+9e///vDn///////////Q////yf/////+7+b/05yA/65ZLv+9dVD/sF40/5kzAP/kvKb//vTu//Tr5v/7+Pb//vfz//707f//////////6f///8X//////vDm/+K4ov/KjGz//ure/8uNbf+jRBX/+OTX/+3b0v+jSBr/pk0h/717Wv/Wrpr//Pn4/////+b///+i//////7z7f/02Mj/wn5b//vl2P+uWS7/vXhU//v49//48u//1q6a/717Wv+oUSb/tWxH//jz8P/////K////V///////+/j//ure/8aFZP/fs5v/oEAQ/9q1o/+zaEL/1ayX//718P/+9/P/+PHu//jz8P//////////h////wr////O///////38v/YpYr/tGQ7/6ZLHf/06eX/s2dB/549Df/x49z//vDn//7x6f//////////8////yoAAAAA////R/////v/////7dXI/5kzAP+7cUv//vHp/+vYzv+bNwX/vHlY//38/P///////////////30AAAAAAAAAAAAAAAD///9n////+/z5+P++e1n/3LGc//7w5//++PT/0KKL/8OIa//9/Pv//////////5X///8GAAAAAAAAAAAAAAAAAAAAAP///0n////K///////////////////////////+/v7/////5v///2z///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Cv///1f///+g////xP///8n///+r////bP///xoAAAAAAAAAAAAAAAAAAAAA+B////AH///AA///wAH//4AB//+AAP//AAD//wAA//8AAP//AAD//4AA//+AAf//wAP//+AD///wD////D///w==","_urls":[{"template":"http://www.answers.com/main/ntquery","rels":[],"params":[{"name":"s","value":"{searchTerms}"},{"name":"gwp","value":"13"}]},{"template":"http://www.answers.com/main/startswith?output=json&client=firefox&s={searchTerms}","rels":[],"type":"application/x-suggestions+json","params":[]}],"filePath":"/usr/lib/firefox-addons/searchplugins/en-US/answers.xml","_installLocation":3,"queryCharset":"UTF-8"}]}}} \ No newline at end of file diff --git a/src/test/profile/selenium/firefoxprofile/search.sqlite b/src/test/profile/selenium/firefoxprofile/search.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..d0a8616aea17941990a5d6872e8d996a0c2f1515 Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/search.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/secmod.db b/src/test/profile/selenium/firefoxprofile/secmod.db new file mode 100644 index 0000000000000000000000000000000000000000..a2fbcf804aab7efab2130286863e762f59beb00b Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/secmod.db differ diff --git a/src/test/profile/selenium/firefoxprofile/sessionstore.js b/src/test/profile/selenium/firefoxprofile/sessionstore.js new file mode 100644 index 0000000000000000000000000000000000000000..3ea3703b7ac7753b50030c05b196710f50605eb0 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/sessionstore.js @@ -0,0 +1 @@ +({"windows":[{"tabs":[{"entries":[{"url":"about:home","title":"Welcome to Ubuntu 10.10!","ID":0,"owner_b64":"NhAra3tiRRqhyKDUVsktxQAAAAAAAAAAwAAAAAAAAEYAAQAAAAAAAS8nfAAOr03buTZBMmukiq4HoizADOUR05MxABBLoP1AAAAAAAVhYm91dAAAAARob21l4NodcC97EdOM0ABgsPwUoweiLMAM5RHTkzEAEEug/UAAAAAADm1vei1zYWZlLWFib3V0AAAABGhvbWUAAAA=","scroll":"0,0"}],"index":1,"attributes":{},"_formDataSaved":true}],"selected":1,"_closedTabs":[],"_hosts":{},"width":820,"height":956,"screenX":0,"screenY":40,"sizemode":"normal"}],"selectedWindow":1,"_closedWindows":[],"session":{"state":"stopped"}}) \ No newline at end of file diff --git a/src/test/profile/selenium/firefoxprofile/urlclassifier3.sqlite b/src/test/profile/selenium/firefoxprofile/urlclassifier3.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..c1440d8ac150e62c351cf3ae18135c5ce383074a Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/urlclassifier3.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/webappsstore.sqlite b/src/test/profile/selenium/firefoxprofile/webappsstore.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..b982b444ff32431b65dfc0b216e37cebfc96c75f Binary files /dev/null and b/src/test/profile/selenium/firefoxprofile/webappsstore.sqlite differ diff --git a/src/test/profile/selenium/firefoxprofile/xpti.dat b/src/test/profile/selenium/firefoxprofile/xpti.dat new file mode 100644 index 0000000000000000000000000000000000000000..fcf0b9ae523445f0fb0978fc7874693cc8b14ff4 --- /dev/null +++ b/src/test/profile/selenium/firefoxprofile/xpti.dat @@ -0,0 +1,1442 @@ +# Generated file. ** DO NOT EDIT! ** + +[Header,2] +0,Version,2,0 +1,AppDir,/usr/lib/firefox-3.6.16 + +[Directories,3] +0,/usr/lib/firefox-3.6.16/components +1,/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/firebug@software.joehewitt.com/components +2,/usr/share/mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}/ubufox@ubuntu.com/components + +[Files,1] +0,browser.xpt,0,364841,1300895268000 + +[ArchiveItems,0] + +[Interfaces,1425] +0,nsIDOMStyleSheet,{a6cf9080-15b3-11d2-932e-00805f8add32},0,-1,1 +1,nsIAddonSearchResultsCallback,{a6f70917-dd30-4eb6-8b3d-453204f96f33},0,-1,1 +2,inIDOMView,{fbb67442-27a3-483c-8eb2-29c3eed7514c},0,-1,1 +3,txIXPathObject,{67706346-dece-4c9b-9fc2-57cf19071014},0,-1,1 +4,nsIUnicharStreamListener,{4a7e9b62-fef8-400d-9865-d6820f630b4c},0,-1,1 +5,nsIContentSniffer,{a5772d1b-fc63-495e-a169-96e8d3311af0},0,-1,1 +6,extIPreferenceBranch,{ce697d40-aa5a-11db-abbd-0800200c9a66},0,-1,1 +7,nsIDOMMediaList,{9b0c2ed7-111c-4824-adf9-ef0da6dad371},0,-1,1 +8,nsISHContainer,{65281ba2-988a-11d3-bdc7-0050040a9b44},0,-1,1 +9,nsITimer,{193fc37a-8aa4-4d29-aa57-1acd87c26b66},0,-1,1 +10,nsIBrowserSearchService,{8307b8f2-08ea-45b8-96bf-b1dc7688fe3b},0,-1,1 +11,nsIDOMHTMLAudioElement,{5ecd8913-a738-41be-8597-7f3a4ffba017},0,-1,1 +12,nsIDOMNSDataTransfer,{990758e9-fd38-4444-a1e8-395195802bda},0,-1,1 +13,nsIThreadPool,{d628159b-1a03-4985-aa77-43122eb23bfc},0,-1,1 +14,nsIScrollBoxObject,{56e2ada8-4631-11d4-ba11-001083023c1e},0,-1,1 +15,nsICachingChannel,{830d4bcb-3e46-4011-9bda-51a5d1af891f},0,-1,1 +16,nsIDNSService,{c1a56a45-8fa3-44e6-9f01-38c91c858cf9},0,-1,1 +17,nsIDOMCSSUnknownRule,{a6cf90d0-15b3-11d2-932e-00805f8add32},0,-1,1 +18,nsIDragDropHandler,{4f418f58-f834-4736-a755-e0395bedca9d},0,-1,1 +19,nsIDOMSVGAnimatedInteger,{7b196db6-955e-4a9f-8f42-645ebc2ce938},0,-1,1 +20,nsIJARURI,{b0922a89-f87b-4cb5-8612-305a285fcca7},0,-1,1 +21,nsITableEditor,{4805e684-49b9-11d3-9ce4-ed60bd6cb5bc},0,-1,1 +22,nsIZipReader,{5cce7f53-23b3-47f8-be05-122c0ba703fd},0,-1,1 +23,nsIDOMStorageManager,{c8e54beb-48f3-4538-a0ce-d6229f4d8f45},0,-1,1 +24,nsIPropertyBag2,{625cfd1e-da1e-4417-9ee9-dbc8e0b3fd79},0,-1,1 +25,nsILocalFile,{aa610f20-a889-11d3-8c81-000064657374},0,-1,1 +26,nsIURIFixup,{773081ac-9f81-4bdb-9e7a-5e87b4361f09},0,-1,1 +27,nsIDOMStorageItem,{0cc37c78-4c5f-48e1-adfc-7480b8fe9dc4},0,-1,1 +28,nsISupportsPRInt16,{e30d94b0-4a1c-11d3-9890-006008962422},0,-1,1 +29,nsIStorageStream,{604ad9d0-753e-11d3-90ca-34278643278f},0,-1,1 +30,nsIMemory,{59e7e77a-38e4-11d4-8cf5-0060b0fc14a3},0,-1,1 +31,nsITreeSelection,{ab6fe746-300b-4ab4-abb9-1c0e3977874c},0,-1,1 +32,nsIDownloadObserver,{44b3153e-a54e-4077-a527-b0325e40924e},0,-1,1 +33,nsIUnicharStreamLoaderObserver,{6bb3e55b-69c0-4fc9-87e5-bed780d997ce},0,-1,1 +34,nsIFile,{c8c0a080-0868-11d3-915f-d9d889d48e3c},0,-1,1 +35,nsIDocumentLoader,{bbe961ee-59e9-42bb-be50-0331979bb79f},0,-1,1 +36,nsIDOMHTMLTableCellElement,{a6cf90b7-15b3-11d2-932e-00805f8add32},0,-1,1 +37,nsIException,{f3a8d3b4-c424-4edc-8bf6-8974c983ba78},0,-1,1 +38,nsIContentPrefObserver,{746c7a02-f6c1-4869-b434-7c8b86e60e61},0,-1,1 +39,nsICommandParams,{83f892cf-7ed3-490e-967a-62640f3158e1},0,-1,1 +40,nsIUrlClassifierDBService,{7aae3f3a-527d-488b-a448-45dca6db0e80},0,-1,1 +41,nsIRDFDataSource,{0f78da58-8321-11d2-8eac-00805f29f370},0,-1,1 +42,nsIPrefLocalizedString,{ae419e24-1dd1-11b2-b39a-d3e5e7073802},0,-1,1 +43,nsIDOMNotifyPaintEvent,{792e5779-7c39-4817-91a7-fdb3fba6428f},0,-1,1 +44,nsIDOMSVGFEMergeElement,{b860512c-2547-4d1f-bb43-b57b54d39014},0,-1,1 +45,nsIDOMCRMFObject,{16da46c0-208d-11d4-8a7c-006008c844c3},0,-1,1 +46,nsIInterfaceInfoManager,{8b161900-be2b-11d2-9831-006008962422},0,-1,0 +47,nsITextServicesFilter,{5bec321f-59ac-413a-a4ad-8a8d7c50a0d0},0,-1,1 +48,nsIJAR,{04501db2-0409-11d3-bcf8-00805f0e1353},0,-1,1 +49,nsIClientAuthUserDecision,{95c4373e-bdd4-4a63-b431-f5b000367721},0,-1,1 +50,nsILoginManagerPrompter,{68b3cb59-51b8-4c57-bd7f-b2ce955a593d},0,-1,1 +51,nsISearchContext,{31aba0f0-2d93-11d3-8069-00600811a9c3},0,-1,1 +52,nsIDirectoryServiceProvider,{bbf8cab0-d43a-11d3-8cc2-00609792278c},0,-1,1 +53,nsIX509Cert,{f0980f60-ee3d-11d4-998b-00b0d02354a0},0,-1,1 +54,nsISecurityEventSink,{a71aee68-dd38-4736-bd79-035fea1a1ec6},0,-1,1 +55,nsIRDFNode,{0f78da50-8321-11d2-8eac-00805f29f370},0,-1,1 +56,nsIDOMSVGDescElement,{56f539b7-0b3d-4bac-b60d-9efe220216ea},0,-1,1 +57,nsIDOMSVGFEFuncBElement,{8b139fe7-5d21-4af3-beda-414aa089b3fb},0,-1,1 +58,nsIProxyInfo,{3fe9308b-1608-4fa0-933c-c5ec2c6175fd},0,-1,1 +59,nsIDOMHTMLLinkElement,{a6cf9088-15b3-11d2-932e-00805f8add32},0,-1,1 +60,nsISupportsPRUint32,{e01dc470-4a1c-11d3-9890-006008962422},0,-1,1 +61,nsIDOMXMLDocument,{8816d003-e7c8-4065-8827-829b8d07b6e0},0,-1,1 +62,nsIDOMSVGImageElement,{43ae4efe-2610-4cce-8242-279e556a78fa},0,-1,1 +63,nsIUrlClassifierDBServiceWorker,{2af84c09-269e-4fc2-b28f-af56717db118},0,-1,1 +64,nsIXSLTProcessorObsolete,{3fbff728-2d20-11d3-aef3-00108300ff91},0,-1,1 +65,nsIWebBrowserSetup,{f15398a0-8018-11d3-af70-00a024ffc08c},0,-1,1 +66,nsIDOMHTMLParagraphElement,{a6cf90a1-15b3-11d2-932e-00805f8add32},0,-1,1 +67,nsIAssociatedContentSecurity,{8db92dde-799f-4d33-80f7-459cac800dc9},0,-1,1 +68,nsIRunnable,{4a2abaf0-6886-11d3-9382-00104ba0fd40},0,-1,1 +69,nsIDirectoryService,{57a66a60-d43a-11d3-8cc2-00609792278c},0,-1,1 +70,extIExtension,{10cee02c-f6e0-4d61-ab27-c16572b18c46},0,-1,1 +71,nsIDNSListener,{41466a9f-f027-487d-a96c-af39e629b8d2},0,-1,1 +72,nsIPK11TokenDB,{4ee28c82-1dd2-11b2-aabf-bb4017abe395},0,-1,1 +73,nsIDOMSVGAnimatedNumberList,{93ebb030-f82d-4f8e-b133-d1b5abb73cf3},0,-1,1 +74,nsIAccessibleText,{0f4633b1-550c-4b50-8c04-0eb1005eef2f},0,-1,1 +75,nsICommandLineValidator,{5ecaa593-7660-4a3a-957a-92d5770671c7},0,-1,1 +76,nsICommandLineHandler,{d4b123df-51ee-48b1-a663-002180e60d3b},0,-1,1 +77,nsICookieManager,{aaab6710-0f2c-11d5-a53b-0010a401eb10},0,-1,1 +78,mozIStorageService,{fe8e95cb-b377-4c8d-bccb-d9198c67542b},0,-1,1 +79,nsPIDNSService,{a26c5b45-7707-4412-bbc1-2462b890848d},0,-1,1 +80,nsIMIMEHeaderParam,{ddbbdfb8-a1c0-4dd5-a31b-5d2a7a3bb6ec},0,-1,1 +81,xpcIJSWeakReference,{5b776cd4-952b-45a2-b363-84e99e8fe608},0,-1,1 +82,mozIPersonalDictionary,{7ef52eaf-b7e1-462b-87e2-5d1dbaca9048},0,-1,1 +83,nsIInstallLocation,{32a74707-ec7c-af19-f4d8-d0cd8cb6a948},0,-1,1 +84,nsISerializable,{91cca981-c26d-44a8-bebe-d9ed4891503a},0,-1,1 +85,nsICurrentCharsetListener,{cf9428c1-df50-11d3-9d0c-0050040007b2},0,-1,1 +86,nsIStringEnumerator,{50d3ef6c-9380-4f06-9fb2-95488f7d141c},0,-1,1 +87,nsICipherInfoService,{766d47cb-6d8c-4e71-b6b7-336917629a69},0,-1,1 +88,nsIDOMSerializer,{9fd4ba15-e67c-4c98-b52c-7715f62c9196},0,-1,1 +89,nsICacheMetaDataVisitor,{22f9a49c-3cf8-4c23-8006-54efb11ac562},0,-1,1 +90,nsIDownloadManagerUI,{ca7663d5-69e3-4c4a-b754-f462bd36b05f},0,-1,1 +91,nsIPKCS11Slot,{c2d4f296-ee60-11d4-998b-00b0d02354a0},0,-1,1 +92,nsIGeneratingKeypairInfoDialogs,{11bf5cdc-1dd2-11b2-ba6a-c76afb326fa1},0,-1,1 +93,jsdIEphemeral,{46f1e23e-1dd2-11b2-9ceb-8285f2e95e69},0,-1,1 +94,nsIWorker,{daf945c3-8d29-4724-8939-dd383f7d27a7},0,-1,1 +95,nsIPrompt,{a63f70c0-148b-11d3-9333-00104ba0fd40},0,-1,1 +96,nsIAuthPromptAdapterFactory,{60e46383-bb9a-4860-8962-80d9c5c05ddc},0,-1,1 +97,nsIDOMNSHTMLScriptElement,{5b2065d7-7888-4529-8a29-e58390a40bd2},0,-1,1 +98,nsIUrlClassifierCallback,{4ca27b6b-a674-4b3d-ab30-d21e2da2dffb},0,-1,1 +99,nsIApplicationCacheChannel,{9acfd21c-9c07-459f-8dae-ed2ffba23ddc},0,-1,1 +100,nsIXULBuilderListener,{ac46be8f-c863-4c23-84a2-d0fcc8dfa9f4},0,-1,1 +101,nsIDownloader,{fafe41a9-a531-4d6d-89bc-588a6522fb4e},0,-1,1 +102,nsICacheVisitor,{f8c08c4b-d778-49d1-a59b-866fdc500d95},0,-1,1 +103,nsIOutputStream,{0d0acd2a-61b4-11d4-9877-00c04fa0cf4a},0,-1,1 +104,nsIDOMCounter,{31adb439-0055-402d-9b1d-d5ca94f3f55b},0,-1,1 +105,nsIHTTPHeaderListener,{ea51e0b8-871c-4b85-92da-6f400394c5ec},0,-1,1 +106,jsdIObject,{a735a94c-9d41-4997-8fcb-cfa8b649a5b7},0,-1,1 +107,nsIDOMSVGTransformList,{cee0a9d4-8554-4bf6-bf9b-7d0cebb4269d},0,-1,1 +108,nsISecureBrowserUI,{081e31e0-a144-11d3-8c7c-00609792278c},0,-1,1 +109,nsIAppStartup2,{3012668f-44b6-49b1-89fb-761a912a78c1},0,-1,1 +110,nsICertPickDialogs,{51d59b08-1dd2-11b2-ad4a-a51b92f8a184},0,-1,1 +111,nsIToolkit,{18032bd0-b265-11d1-aa2a-000000000000},0,-1,0 +112,nsISupportsFloat,{abeaa390-4ac0-11d3-baea-00805f8a5dd7},0,-1,1 +113,nsIDOMHTMLSelectElement,{a6cf9090-15b3-11d2-932e-00805f8add32},0,-1,1 +114,nsIAutoCompleteInput,{f5eddd39-f8e0-43b7-bc3d-03623f595e52},0,-1,1 +115,nsIContextMenuInfo,{2f977d56-5485-11d4-87e2-0010a4e75ef2},0,-1,1 +116,nsIMultiPartChannel,{ba78db7b-b88c-4b76-baf9-3c2296a585ae},0,-1,1 +117,nsIUnicharLineInputStream,{67f42475-ba80-40f8-ac0b-649c89230184},0,-1,1 +118,nsIDOMGeoPositionAddress,{0df49c5c-9845-42f9-a76c-62e09c110986},0,-1,1 +119,nsIINIParserWriter,{712dc5da-8d09-45d0-ba2e-de27eb384c4c},0,-1,1 +120,nsITokenDialogs,{a1cbc159-468c-495d-8068-61dd538cbcca},0,-1,1 +121,nsILoginManager,{30534ff7-fb95-45c5-8336-5448638f2aa1},0,-1,1 +122,nsIDOMDocumentCSS,{39f76c23-45b2-428a-9240-a981e5abf148},0,-1,1 +123,nsIScriptableRegion,{4d179656-a5bd-42a6-a937-c81f820dcf2f},0,-1,1 +124,nsITransportSecurityInfo,{0d0a6b62-d4a9-402e-a197-6bc6e358fec9},0,-1,1 +125,nsPIPromptService,{c60a1955-6cb3-4827-8ef8-4f5c668af0b3},0,-1,0 +126,nsITextToSubURI,{8b042e24-6f87-11d3-b3c8-00805f8a6670},0,-1,1 +127,nsIAccessibleTableCell,{654e296d-fae6-452b-987d-746b20b9514b},0,-1,1 +128,nsITokenPasswordDialogs,{be26b580-1dd1-11b2-9946-c598d0d07727},0,-1,1 +129,nsIDataSignatureVerifier,{0a84b3d5-6ba9-432d-89da-4fbd0b0f2aec},0,-1,1 +130,jsdIExecutionHook,{3a722496-9d78-4f0a-a797-293d9e8cb8d2},0,-1,1 +131,nsINavBookmarkObserver,{1f7e9032-b2c0-4561-b35b-94ba3f8344e2},0,-1,1 +132,nsIDOMPopupBlockedEvent,{05be571f-c3ea-4959-a340-c57b1591ae4b},0,-1,1 +133,nsIFeedWriter,{67003393-018c-4e96-af10-c6c51a049fad},0,-1,1 +134,nsIDOMSVGFECompositeElement,{6ff3c539-1a3b-4a3f-8acd-354d349eb7fc},0,-1,1 +135,nsIXPIProgressDialog,{ce8f744e-d5a5-41b3-911f-0fee3008b64e},0,-1,1 +136,nsISupportsChar,{e2b05e40-4a1c-11d3-9890-006008962422},0,-1,1 +137,nsISelectionPrivate,{98552206-ad7a-4d2d-8ce3-b6fa2389298b},0,-1,1 +138,nsIXPCConstructor,{c814ca20-e0dc-11d3-8f5f-0010a4e73d9a},0,-1,1 +139,nsIDOMSVGZoomEvent,{339a8c7a-552e-4cbc-8d96-8370a3939358},0,-1,1 +140,nsICancelable,{d94ac0a0-bb18-46b8-844e-84159064b0bd},0,-1,1 +141,nsIDOMHTMLCanvasElement,{d87394af-d31a-484e-8b7c-75381045384d},0,-1,1 +142,nsIJARChannel,{6e6cc56d-51eb-4299-a795-dcfd1229ab3d},0,-1,1 +143,nsIFeedProgressListener,{ebfd5de5-713c-40c0-ad7c-f095117fa580},0,-1,1 +144,nsIDOMLSSerializerFilter,{b9b6ec85-f69f-4a5a-a96a-8a7a8f07e2b4},0,-1,1 +145,nsIBinaryOutputStream,{204ee610-8765-11d3-90cf-0040056a906e},0,-1,1 +146,nsIDOMDOMStringList,{0bbae65c-1dde-11d9-8c46-000a95dc234c},0,-1,1 +147,nsIAccessibleHyperText,{d56bd454-8ff3-4edc-b266-baeada00267b},0,-1,1 +148,nsIExceptionService,{35a88f54-f267-4414-92a7-191f6454ab52},0,-1,1 +149,nsIDOMSVGPathSegLinetoVerticalAbs,{fd5ffb7b-7279-4c09-abfd-b733dc872e80},0,-1,1 +150,nsIAutoCompleteResult,{d2fcba9a-3f5c-40fc-a9fc-4adc87dc61ef},0,-1,1 +151,nsIDOMWindowUtils_1_9_2_5,{915abb48-66d4-4135-a0d8-153fb87b99e6},0,-1,1 +152,nsIThreadInternal,{f89b5063-b06d-42f8-bf23-4dfcf2d80d6a},0,-1,1 +153,nsIDOMCSSMediaRule,{a6cf90bc-15b3-11d2-932e-00805f8add32},0,-1,1 +154,imgIDecoder,{9eebf43a-1dd1-11b2-953e-f1782f4cbad3},0,-1,1 +155,nsIRDFInMemoryDataSource,{17c4e0aa-1dd2-11b2-8029-bf6f668de500},0,-1,1 +156,nsIFeed,{3b8aae33-80e2-4efa-99c8-a6c5b99f76ea},0,-1,1 +157,nsIAccessibleProvider,{3f7f9194-c625-4a85-8148-6d92d34897fa},0,-1,1 +158,nsIDOMHTMLPreElement,{a6cf90a4-15b3-11d2-932e-00805f8add32},0,-1,1 +159,nsIDOMMouseScrollEvent,{ba8d1a7e-b475-4542-8d32-01e7ea7b8091},0,-1,1 +160,nsIDOMSVGUseElement,{d49a3ac7-e779-46c8-ae92-214420aa1b71},0,-1,1 +161,nsIAccessibleSelectable,{34d268d6-1dd2-11b2-9d63-83a5e0ada290},0,-1,1 +162,nsPICommandUpdater,{b135f602-0bfe-11d5-a73c-f0e420e8293c},0,-1,1 +163,nsIDOMDocumentType,{a6cf9077-15b3-11d2-932e-00805f8add32},0,-1,1 +164,nsIExternalProtocolService,{70f93b7a-3ec6-4bcb-b093-92d9984c9f83},0,-1,1 +165,nsIPrivateBrowsingService,{49d6f133-80c0-48c7-876d-0b70bbfd0289},0,-1,1 +166,nsIUTF8ConverterService,{249f52a3-2599-4b00-ba40-0481364831a2},0,-1,1 +167,nsIDOMXULLabelElement,{c987629e-6370-45f5-86ec-aa765fa861cd},0,-1,1 +168,nsIDOMDOMException,{a6cf910a-15b3-11d2-932e-00805f8add32},0,-1,1 +169,mozIStoragePendingStatement,{00da7d20-3768-4398-bedc-e310c324b3f0},0,-1,1 +170,nsIStreamConverter,{0b6e2c69-5cf5-48b0-9dfd-c95950e2cc7b},0,-1,1 +171,nsIContentViewerContainer,{ea2ce7a0-5c3d-11d4-90c2-0050041caf44},0,-1,1 +172,nsIAppStartup,{6799abed-4721-4f51-9304-d1a2ea1df5d5},0,-1,1 +173,nsICookie2,{05c420e5-03d0-4c7b-a605-df7ebe5ca326},0,-1,1 +174,nsIPKCS11ModuleDB,{ff9fbcd7-9517-4334-b97a-ceed78909974},0,-1,1 +175,nsIBrowserInstance,{8af0fa40-598d-11d3-806a-00600811a9c3},0,-1,1 +176,nsIOCSPResponder,{96b2f5ae-4334-11d5-ba27-00108303b117},0,-1,1 +177,nsIAddonUpdateCheckListener,{c946119f-9e7c-41aa-a794-803148045350},0,-1,1 +178,nsIRandomGenerator,{2362d97a-747a-4576-8863-697667309209},0,-1,1 +179,nsIAccessibleTextChangeEvent,{50a1e151-8e5f-4bcc-aaaf-a4bed1190e93},0,-1,1 +180,nsIDOMCDATASection,{a6cf9071-15b3-11d2-932e-00805f8add32},0,-1,1 +181,nsIXPCScriptable,{5d309b93-e9b4-4374-bcd5-44245c83408f},0,-1,0 +182,nsIProtocolProxyFilter,{f424abd3-32b4-456c-9f45-b7e3376cb0d1},0,-1,1 +183,nsIDOMXULContainerItemElement,{4650e55f-4777-4271-8b62-9603a7dd4614},0,-1,1 +184,nsISSLSocketControl,{a092097c-8386-4f1b-97b1-90eb70008c2d},0,-1,1 +185,nsISSLErrorListener,{99f8d972-bae4-414c-b39b-47587d3ded68},0,-1,1 +186,nsIContentHandler,{49439df2-b3d2-441c-bf62-866bdaf56fd2},0,-1,1 +187,nsIPKIParamBlock,{b6fe3d78-1dd1-11b2-9058-ced9016984c8},0,-1,1 +188,nsICache,{ec1c0063-197d-44bb-84ba-7525d50fc937},0,-1,1 +189,nsIBufEntropyCollector,{485b87a8-5dd7-4b8d-8ea8-dee53201f899},0,-1,0 +190,nsIDOMFile,{0845e8ae-56bd-4f0e-962a-3b3e92638a0b},0,-1,1 +191,nsIHTMLEditor,{afc36593-5787-4420-93d9-b2c0ccbf0cad},0,-1,1 +192,nsIDOMSVGPathSegLinetoRel,{7933a81a-72c5-4489-ba64-5635f4c23063},0,-1,1 +193,jsdIStackFrame,{0633ca73-105e-4e8e-bcc5-13405d61754a},0,-1,1 +194,nsISHEntry,{09fecea6-5453-43ba-bf91-3ff32618f037},0,-1,1 +195,nsISHistoryInternal,{7ca0fd71-437c-48ad-985d-11ce9e2429b4},0,-1,1 +196,nsIGnomeVFSService,{dea20bf0-4e4d-48c5-b932-dc3e116dc64b},0,-1,1 +197,nsITreeContentView,{5ef62896-0c0a-41f1-bb3c-44a60f5dfdab},0,-1,1 +198,nsIDOMSVGPathSegLinetoHorizontalRel,{8693268c-5180-43fd-acc3-5b9c09f43386},0,-1,1 +199,nsIXPIDialogService,{8cdd8baa-1dd2-11b2-909a-f0178da5c5ff},0,-1,1 +200,nsIDOMGeoPositionCallback,{527e8b53-6f29-4b6a-8d04-5c1666a4c4c1},0,-1,1 +201,nsIAutoCompleteSimpleResult,{f9841787-ad26-49e6-a2dd-ba9020ee1c64},0,-1,1 +202,nsIFocusManager,{cd6040a8-243f-412a-8a16-0bf2aa1083b9},0,-1,1 +203,nsIAccessibleEditableText,{52837507-202d-4e72-a482-5f068a1fd720},0,-1,1 +204,nsIWorkerMessagePort,{ab3725b8-3fca-40cc-a42c-92fb154ef01d},0,-1,1 +205,nsIAboutModule,{9575693c-60d9-4332-b6b8-6c29289339cb},0,-1,1 +206,nsIDOMNotation,{a6cf907e-15b3-11d2-932e-00805f8add32},0,-1,1 +207,nsIProxyObjectManager,{ee8ce1e3-0319-4bd9-8f70-7258b21c7733},0,-1,1 +208,fuelIApplication,{fe74cf80-aa2d-11db-abbd-0800200c9a66},0,-1,1 +209,nsIObserver,{db242e01-e4d9-11d2-9dde-000064657374},0,-1,1 +210,nsIAuthInformation,{0d73639c-2a92-4518-9f92-28f71fea5f20},0,-1,1 +211,nsIProfileLock,{50e07b0a-f338-4da3-bcdb-f4bb0db94dbe},0,-1,1 +212,nsIAutoCompleteSimpleResultListener,{004efdc5-1989-4874-8a7a-345bf2fa33af},0,-1,1 +213,nsINavHistoryObserver,{14065711-8a91-4d96-ba32-59512f5401b6},0,-1,1 +214,nsIFileOutputStream,{e6f68040-c7ec-11d3-8cda-0060b0fc14a3},0,-1,1 +215,nsIFind,{75125d55-37ee-4575-b9b5-f33bfa68c2a1},0,-1,1 +216,nsIXTFPrivate,{13ef3d54-1dd1-4a5c-a8d5-a04a327fb9b6},0,-1,1 +217,nsIPlaintextEditor,{1480e196-0d5c-40cf-8563-ed8a33eabcf2},0,-1,1 +218,nsIDOMNSHTMLSelectElement,{a6cf9105-15b3-11d2-932e-00805f8add32},0,-1,1 +219,nsIDOMHTMLModElement,{a6cf90a9-15b3-11d2-932e-00805f8add32},0,-1,1 +220,nsIDOMFileInternal,{047ca6c4-52b3-46f1-8976-e198b724f72f},0,-1,1 +221,nsIPluginInputStream,{af160530-542a-11d2-8164-006008119d7a},0,-1,0 +222,nsICRLInfo,{c185d920-4a3e-11d5-ba27-00108303b117},0,-1,1 +223,nsIDOMCSSMozDocumentRule,{4eb9adac-afaf-4b8a-8640-7340863c1587},0,-1,1 +224,nsIAccessibleRelation,{f42a1589-70ab-4704-877f-4a9162bbe188},0,-1,1 +225,nsIDOMSVGEllipseElement,{5d1cd1e6-4a14-4056-acc0-2f78c1672898},0,-1,1 +226,jsdIContext,{3e5c934d-6863-4d81-96f5-76a3b962fc2b},0,-1,1 +227,nsIDOMDocumentTraversal,{13f236c0-47f8-11d5-b6a3-009027446e84},0,-1,1 +228,nsIFeedProcessor,{8a0b2908-21b0-45d7-b14d-30df0f92afc7},0,-1,1 +229,nsIXTFAttributeHandler,{72152f7f-7e8d-43fd-8477-3f29ae8d240d},0,-1,1 +230,nsISupportsWeakReference,{9188bc86-f92e-11d2-81ef-0060083a0bcf},0,-1,1 +231,nsIDOMSVGElement,{e0be7cbb-81c1-4663-8f95-109d96a60b6b},0,-1,1 +232,nsIDOM3DocumentEvent,{090ecc19-b7cb-4f47-ae47-ed68d4926249},0,-1,1 +233,nsIRDFRemoteDataSource,{1d297320-27f7-11d3-be01-000064657374},0,-1,1 +234,nsIDOMSVGPathSegLinetoHorizontalAbs,{4a54a4d2-edef-4e19-9600-2330311000f4},0,-1,1 +235,nsIAsyncInputStream,{a5f255ab-4801-4161-8816-277ac92f6ad1},0,-1,1 +236,nsIDOMText,{a6cf9082-15b3-11d2-932e-00805f8add32},0,-1,1 +237,nsIDOMRect,{71735f62-ac5c-4236-9a1f-5ffb280d531c},0,-1,1 +238,nsICRLManager,{486755db-627a-4678-a21b-f6a63bb9c56a},0,-1,1 +239,nsIHttpEventSink,{9475a6af-6352-4251-90f9-d65b1cd2ea15},0,-1,1 +240,nsIX509Cert3,{399004d8-b8c7-4eb9-8362-d99f4c0161fd},0,-1,1 +241,nsISearchEngine,{803e510b-4b27-4ba2-a16d-bb5fa953c166},0,-1,1 +242,nsIUrlListManagerCallback,{fa4caf12-d057-4e7e-81e9-ce066ceee90b},0,-1,1 +243,nsIDOMXPathNamespace,{75506f87-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +244,nsIDOMHTMLHRElement,{a6cf90a8-15b3-11d2-932e-00805f8add32},0,-1,1 +245,fuelIBookmarkRoots,{c9a80870-eb3c-11dc-95ff-0800200c9a66},0,-1,1 +246,nsIXULTemplateRuleFilter,{819cd1ed-8010-42e1-a8b9-778b726a1ff3},0,-1,1 +247,nsIWebBrowserFocus,{9c5d3c58-1dd1-11b2-a1c9-f3699284657a},0,-1,1 +248,nsISAXErrorHandler,{e02b6693-6cca-11da-be43-001422106990},0,-1,1 +249,nsIHTMLObjectResizer,{8b396020-69d3-451f-80c1-1a96a7da25a9},0,-1,1 +250,nsIXMLContentBuilder,{e9c4cd4f-cd41-43d0-bf3b-48abb9cde90f},0,-1,1 +251,nsIInputStreamCallback,{d1f28e94-3a6e-4050-a5f5-2e81b1fc2a43},0,-1,1 +252,nsISupportsPRUint64,{e13567c0-4a1c-11d3-9890-006008962422},0,-1,1 +253,nsIClipboard,{38984945-8674-4d04-b786-5c0ca9434457},0,-1,1 +254,nsPIPlacesHistoryListenersNotifier,{b96adaff-e02c-48da-a379-8af5d10e09af},0,-1,1 +255,inIDOMUtils,{78fd16c2-bdfb-4b1d-8738-d536d0a8f430},0,-1,1 +256,nsIToolkitProfileService,{9b434f48-438c-4f85-89de-b7f321a45341},0,-1,1 +257,nsIRandomAccessIterator,{9bd6fdb0-1dd1-11b2-9101-d15375968230},0,-1,1 +258,nsITransactionListener,{58e330c4-7b48-11d2-98b9-00805f297d89},0,-1,1 +259,nsICookiePermission,{4b1a775d-f6d3-4389-be2e-9dfbaf2ab47b},0,-1,1 +260,nsIContentPolicy,{344f9cb0-9a17-44c5-ab96-ee707884266c},0,-1,1 +261,nsIWyciwygChannel,{89b0674a-9e2f-4124-9b59-481444be841d},0,-1,1 +262,nsIHelperAppLauncher,{d9a19faf-497b-408c-b995-777d956b72c0},0,-1,1 +263,nsIDOMCharacterData,{a6cf9072-15b3-11d2-932e-00805f8add32},0,-1,1 +264,nsITransaction,{58e330c1-7b48-11d2-98b9-00805f297d89},0,-1,1 +265,nsIRDFContainerUtils,{d4214e91-fb94-11d2-bdd8-00104bde6048},0,-1,1 +266,nsIRelativeFilePref,{2f977d4e-5485-11d4-87e2-0010a4e75ef2},0,-1,1 +267,mozIStorageConnection,{ac3c486c-69a1-4cbe-8f25-2ad20880eab3},0,-1,1 +268,nsIDOMClientRect,{b2f824c4-d9d3-499b-8d3b-45c8245497c6},0,-1,1 +269,nsINavHistoryQueryResultNode,{ea17745a-1852-4155-a98f-d1dd1763b3df},0,-1,1 +270,nsIDOMDocumentStyle,{3d9f4973-dd2e-48f5-b5f7-2634e09eadd9},0,-1,1 +271,nsIURIContentListener,{94928ab3-8b63-11d3-989d-001083010e9b},0,-1,1 +272,nsIRDFObserver,{3cc75360-484a-11d2-bc16-00805f912fe7},0,-1,1 +273,nsITransportEventSink,{eda4f520-67f7-484b-a691-8c3226a5b0a6},0,-1,1 +274,nsIDOMPlugin,{ff69a292-c74d-4ef5-9d0f-86112fff2d5b},0,-1,1 +275,nsIWebBrowser,{69e5df00-7b8b-11d3-af61-00a024ffc08c},0,-1,1 +276,nsIRDFXMLSource,{4da56f10-99fe-11d2-8ebb-00805f29f370},0,-1,1 +277,nsIDOMElement,{a6cf9078-15b3-11d2-932e-00805f8add32},0,-1,1 +278,nsICookieManager2,{d1e9e50f-b78b-4e3b-a474-f3cbca59b013},0,-1,1 +279,nsIDOMSVGTextElement,{6d43b1b4-efb6-426d-9e65-4420c3e24688},0,-1,1 +280,jsdIFilter,{0c9189d9-4287-47a4-bca6-6ed65aaf737f},0,-1,1 +281,nsIDOMCSSStyleRule,{a6cf90bf-15b3-11d2-932e-00805f8add32},0,-1,1 +282,nsIDOMClientInformation,{f8bbf8c3-c47b-465a-a221-22824449f689},0,-1,1 +283,nsIContentViewer,{08665a60-b398-11de-8a39-0800200c9a66},0,-1,1 +284,nsIDOMJSWindow,{14efb76c-5bd6-449e-b36f-0cbd22981f20},0,-1,1 +285,nsIDOMSVGAnimatedLengthList,{bfa6e42b-bc9d-404d-8688-729fdbfff801},0,-1,1 +286,nsIStreamConverterService,{f2b1ab53-f0bd-4adb-9365-e59b1701a258},0,-1,1 +287,nsIFastLoadReadControl,{652ecec6-d40b-45b6-afef-641d6c63a35b},0,-1,1 +288,nsIWebBrowserChrome2,{2585a7b1-7b47-43c4-bf17-c6bf84e09b7b},0,-1,1 +289,nsIBidiKeyboard,{0d8f8f10-c92d-4a6a-b2bb-e1921f3f4dda},0,-1,1 +290,nsIXPConnectWrappedJS,{bed52030-bca6-11d2-ba79-00805f8a5dd7},0,-1,0 +291,nsIHTMLInlineTableEditor,{eda2e65c-a758-451f-9b05-77cb8de74ed2},0,-1,1 +292,nsIAutoCompleteController,{46a86173-0ab5-44b2-ab51-722cb3db1b60},0,-1,1 +293,nsIDOMSVGAnimatedPreserveAspectRatio,{afcd7cd4-d74d-492f-b3b1-d71bfa36874f},0,-1,1 +294,nsIPrefBranch,{56c35506-f14b-11d3-99d3-ddbfac2ccf65},0,-1,1 +295,nsIBrowserHistory,{b333c6dd-3dbe-4c0b-8062-92ed92b7e7c9},0,-1,1 +296,nsISelectionListener,{a6cf90e2-15b3-11d2-932e-00805f8add32},0,-1,1 +297,nsIWebHandlerApp,{7521a093-c498-45ce-b462-df7ba0d882f6},0,-1,1 +298,nsIMIMEInputStream,{dcbce63c-1dd1-11b2-b94d-91f6d49a3161},0,-1,1 +299,jsdIScriptHook,{cf7ecc3f-361b-44af-84a7-4b0d6cdca204},0,-1,1 +300,nsIWindowDataSource,{3722a5b9-5323-4ed0-bb1a-8299f27a4e89},0,-1,1 +301,nsIDOMHTMLByteRanges,{992c540c-4d81-42df-80a6-f71ede2b59d8},0,-1,1 +302,nsIStreamLoaderObserver,{359f7990-d4e9-11d3-a1a5-0050041caf44},0,-1,1 +303,nsIDOMHTMLElement,{a6cf9085-15b3-11d2-932e-00805f8add32},0,-1,1 +304,nsIXTFElementFactory,{27c10dca-2efc-416b-ae36-9794380a661e},0,-1,1 +305,nsIXPInstallManager,{83fdd52f-2d34-4e22-981d-cf3c4ae76faa},0,-1,1 +306,nsIDOMHTMLMediaElement,{505b523e-4a27-4151-b0eb-750b7258760e},0,-1,1 +307,nsIDOMFileReader,{5db0ce80-de44-40c0-a346-e28aac4aa978},0,-1,1 +308,fuelIBookmarkFolder,{9f42fe20-52de-4a55-8632-a459c7716aa0},0,-1,1 +309,nsIBrowserHandler,{8d3f5a9d-118d-4548-a137-cf7718679069},0,-1,1 +310,nsIGeolocationPrompt,{2300c895-1bee-4297-912c-a57082f3e936},0,-1,1 +311,nsIInputStreamTee,{44e8b2c8-1ecb-4a63-8b23-3e3500c34f32},0,-1,1 +312,nsIDOMNodeSelector,{7cebc153-168a-416c-ba5a-56a8c2ddb2ec},0,-1,1 +313,nsIAbstractWorker,{b90b7561-b5e2-4545-84b0-280dbaaa94ea},0,-1,1 +314,nsIWritableVariant,{5586a590-8c82-11d5-90f3-0010a4e73d9a},0,-1,1 +315,nsIFontEnumerator,{924d98d9-3518-4cb4-8708-c74fe8e3ec3c},0,-1,1 +316,nsIDOMNode,{a6cf907c-15b3-11d2-932e-00805f8add32},0,-1,1 +317,nsIDOMSVGPathSegCurvetoCubicSmoothAbs,{5fa8fea8-bdd1-4315-ac44-a39b3ff347b5},0,-1,1 +318,nsIDOMDOMConfiguration,{cfb5b821-9016-4a79-9d98-87b57c3ea0c7},0,-1,1 +319,nsIPKCS11Module,{8a44bdf9-d1a5-4734-bd5a-34ed7fe564c2},0,-1,1 +320,nsIFormatConverter,{948a0023-e3a7-11d2-96cf-0060b0fb9956},0,-1,1 +321,nsIChannel,{c63a055a-a676-4e71-bf3c-6cfa11082018},0,-1,1 +322,nsIDOMDocumentFragment,{a6cf9076-15b3-11d2-932e-00805f8add32},0,-1,1 +323,nsIStreamListenerTee_1_9_2,{18b1e3d7-8083-4b19-a077-82ceea6fd296},0,-1,1 +324,nsIDOMParser,{5677f36e-1842-4c6f-a39c-2e5576ab8b40},0,-1,1 +325,imgILoader,{d2f50c69-1064-4ce3-a92d-01dc5f5b4842},0,-1,1 +326,nsIDOMCSSPageRule,{a6cf90bd-15b3-11d2-932e-00805f8add32},0,-1,1 +327,nsIDOMSVGAnimatedTransformList,{fd54c8c4-2eb4-4849-8df6-79985c2491da},0,-1,1 +328,nsISliderListener,{e5b3074e-ee18-4538-83b9-2487d90a2a34},0,-1,1 +329,nsIJSID,{baedc96a-9cee-4b6b-9160-90d257b3c8ef},0,-1,1 +330,nsIBrowserGlue,{781df699-17dc-4237-b3d7-876ddb7085e3},0,-1,1 +331,nsIExternalProtocolHandler,{0e61f3b2-34d7-4c79-bfdc-4860bc7341b7},0,-1,1 +332,nsIXTFElement,{4f144387-796d-4baf-8641-5db45dba1808},0,-1,1 +333,nsIFilePicker,{d24ef0aa-d555-4117-84af-9cbbb7406909},0,-1,1 +334,nsIPropertyElement,{283ee646-1aef-11d4-98b3-00c04fa0ce9a},0,-1,1 +335,nsIDOMGeoPositionErrorCallback,{7d9b09d9-4843-43eb-a7a7-67f7dda6b3c4},0,-1,1 +336,nsIStandardURL,{babd6cca-ebe7-4329-967c-d6b9e33caa81},0,-1,1 +337,nsIRDFPurgeableDataSource,{951700f0-fed0-11d2-bdd9-00104bde6048},0,-1,1 +338,nsIExtendedExpatSink,{0c2dc80f-7aa4-467a-9454-b89dba0e0779},0,-1,1 +339,nsIWorkerMessageEvent,{508f2d49-e9a0-4fe8-bd33-321820173b4a},0,-1,1 +340,nsISeekableStream,{8429d350-1040-4661-8b71-f2a6ba455980},0,-1,1 +341,nsIHandlerService,{53f0ad17-ec62-46a1-adbc-efccc06babcd},0,-1,1 +342,nsIScriptSecurityManager,{f8e350b9-9f31-451a-8c8f-d10fea26b780},0,-1,1 +343,nsIWindowMediator,{0659cb81-faad-11d2-8e19-b206620a657c},0,-1,1 +344,nsIMicrosummary,{6867dc21-077f-4462-937d-cd8b7c680e0c},0,-1,1 +345,nsIDocumentLoaderFactory,{5e7d2967-5a07-444f-95d5-25b533252d38},0,-1,1 +346,nsIProxiedChannel,{6238f134-8c3f-4354-958f-dfd9d54a4446},0,-1,1 +347,nsIUnicodeNormalizer,{b43a461f-1bcf-4329-820b-66e48c979e14},0,-1,1 +348,nsIStreamListenerTee,{fb683e76-d42b-41a4-8ae6-65a6c2b146e5},0,-1,1 +349,nsIDOM3Text,{bcca052e-46f4-4b8e-8859-a86776c2f1d7},0,-1,1 +350,nsIFeedGenerator,{0fecd56b-bd92-481b-a486-b8d489cdd385},0,-1,1 +351,nsISyncStreamListener,{7e1aa658-6e3f-4521-9946-9685a169f764},0,-1,1 +352,nsIDOMLSParserFilter,{10e8893d-ddf5-45d1-8872-615d72065fb4},0,-1,1 +353,nsIDOMNSDocument,{09a439ad-4079-46d5-a050-4d7015d1a108},0,-1,1 +354,nsIScriptError,{b0196fc7-1913-441a-882a-453c0d8b89b8},0,-1,1 +355,nsIXPConnectJSObjectHolder,{8916a320-d118-11d3-8f3a-0010a4e73d9a},0,-1,0 +356,nsIEditorMailSupport,{fdf23301-4a94-11d3-9ce4-9960496c41bc},0,-1,1 +357,nsIXULWindow,{c175a596-ee13-420a-aa74-13ad3a14deb1},0,-1,1 +358,nsIEventTarget,{4e8febe4-6631-49dc-8ac9-308c1cb9b09c},0,-1,1 +359,nsIURLParser,{7281076d-cf37-464a-815e-698235802604},0,-1,1 +360,nsIGeolocationUpdate,{b89d7227-9f04-4236-a582-25a3f2779d72},0,-1,1 +361,nsIX509CertValidity,{e701dfd8-1dd1-11b2-a172-ffa6cc6156ad},0,-1,1 +362,extIExtensions,{de281930-aa5a-11db-abbd-0800200c9a66},0,-1,1 +363,nsIModule,{7392d032-5371-11d3-994e-00805fd26fee},0,-1,1 +364,nsINativeAppSupport,{5fdf8480-1f98-11d4-8077-00600811a9c3},0,-1,1 +365,nsIDOMSVGMetadataElement,{94558064-140c-41a1-9cc9-4e9cdbf5c124},0,-1,1 +366,nsINavHistoryQueryOptions,{b3d5de06-f8ef-4433-84c2-b8b237403b2a},0,-1,1 +367,nsIRDFDate,{e13a24e1-c77a-11d2-80be-006097b76b8e},0,-1,1 +368,nsIDOMSVGFEDisplacementMapElement,{80e1ea9c-eff3-490a-8c98-918963d2e7e9},0,-1,1 +369,nsIDocCharset,{9c18bb4e-1dd1-11b2-bf91-9cc82c275823},0,-1,1 +370,nsISignatureVerifier,{dea87f65-e91e-4119-aa13-aaa2be80cac2},0,-1,0 +371,nsISocketTransport,{ef3f4993-cfbc-4e5a-9509-16deafe16549},0,-1,1 +372,nsIASN1Object,{ba8bf582-1dd1-11b2-898c-f40246bc9a63},0,-1,1 +373,nsIPrintProgress,{7e46bc35-fb7d-4b45-ab35-82fd61015380},0,-1,1 +374,nsIDOMXULElement,{30a4a815-b42a-4f0b-9c10-1e7f727cd135},0,-1,1 +375,nsIXPCWrappedJSObjectGetter,{254bb2e0-6439-11d4-8fe0-0010a4e73d9a},0,-1,1 +376,nsIDOMMimeType,{f6134682-f28b-11d2-8360-c90899049c3c},0,-1,1 +377,nsIDOMMouseEvent,{ff751edc-8b02-aae7-0010-8301838a3123},0,-1,1 +378,nsIAccessibleEvent,{ba448f0e-a761-48c8-a0f5-1f25e23d4fe4},0,-1,1 +379,nsIDOMNSRGBAColor,{742dc816-5134-4214-adfa-cad9dd3377cd},0,-1,1 +380,nsIInterfaceRequestor,{033a1470-8b2a-11d3-af88-00a024ffc08c},0,-1,1 +381,nsINestedURI,{6de2c874-796c-46bf-b57f-0d7bd7d6cab0},0,-1,1 +382,nsIServiceManager,{8bb35ed9-e332-462d-9155-4a002ab5c958},0,-1,1 +383,nsIDOMHTMLOptGroupElement,{a6cf9091-15b3-11d2-932e-00805f8add32},0,-1,1 +384,nsICommandManager,{080d2001-f91e-11d4-a73c-f9242928207c},0,-1,1 +385,nsIIDNService,{a592a60e-3621-4f19-a318-2bf233cfad3e},0,-1,1 +386,nsIDOMHTMLTitleElement,{a6cf9089-15b3-11d2-932e-00805f8add32},0,-1,1 +387,nsIMemoryReporter,{d298b942-3e66-4cd3-9ff5-46abc69147a7},0,-1,1 +388,nsITraceRefcnt,{273dc92f-0fe6-4545-96a9-21be77828039},0,-1,0 +389,nsITimelineService,{93276790-3daf-11d5-b67d-000064657374},0,-1,1 +390,nsIUnicharOutputStream,{2d00b1bb-8b21-4a63-bcc6-7213f513ac2e},0,-1,1 +391,nsIAppShell,{501403e9-a091-4780-ba55-cfd1e21287a1},0,-1,0 +392,nsIDataType,{4d12e540-83d7-11d5-90ed-0010a4e73d9a},0,-1,1 +393,nsIChromeRegistry,{249fb5ad-ae29-4e2c-a728-ba5cf464d188},0,-1,1 +394,nsIJSON,{45464c36-efde-4cb5-8e00-07480533ff35},0,-1,1 +395,nsINavHistoryVisitResultNode,{8e2c5a86-b33d-4fa6-944b-559af7e95fcd},0,-1,1 +396,nsIDOMCryptoDialogs,{1f8fe77e-1dd2-11b2-8dd2-e55f8d3465b8},0,-1,1 +397,nsIDOMSVGGradientElement,{988b2de4-137b-4bb8-a15e-fe94038e9cf3},0,-1,1 +398,nsIDOMSVGFEImageElement,{3250f5c9-9c76-4e77-96d8-5f0cc85f41c4},0,-1,1 +399,nsIInputStreamPump,{400f5468-97e7-4d2b-9c65-a82aecc7ae82},0,-1,1 +400,nsIDOMLSParser,{2a31a3a0-be68-40af-9f64-914192f0fba2},0,-1,1 +401,nsIDOMCSSStyleDeclaration,{a6cf90be-15b3-11d2-932e-00805f8add32},0,-1,1 +402,nsIOfflineCacheUpdateService,{6fd2030f-7b00-4102-a0e3-d73078821eb1},0,-1,1 +403,nsIRequest,{ef6bfbd2-fd46-48d8-96b7-9f8f0fd387fe},0,-1,1 +404,nsIJSIID,{e76ec564-a080-4705-8609-384c755ec91e},0,-1,1 +405,nsIDOMHTMLTableSectionElement,{a6cf90b5-15b3-11d2-932e-00805f8add32},0,-1,1 +406,nsIDirectoryEnumerator,{31f7f4ae-6916-4f2d-a81e-926a4e3022ee},0,-1,1 +407,imgICache,{f1b74aae-5661-4753-a21c-66dd644afebc},0,-1,1 +408,nsIDOMSVGZoomAndPan,{18967370-921a-4245-8158-a279b190abca},0,-1,1 +409,nsIContainerBoxObject,{35d4c04b-3bd3-4375-92e2-a818b4b4acb6},0,-1,1 +410,nsIProtocolProxyService,{e38ab577-786e-4a7f-936b-7ae4c7d877b2},0,-1,1 +411,nsIEventListenerInfo,{cbc2ea6e-4043-4435-ba8f-64cbf6638622},0,-1,1 +412,nsISupportsPRUint8,{dec2e4e0-4a1c-11d3-9890-006008962422},0,-1,1 +413,nsIDOMSVGStyleElement,{9af0d129-b366-4aa8-b7d8-8dce93148d91},0,-1,1 +414,nsIURILoader,{2f7e8051-f1c9-4bcc-8584-9cfd5849e343},0,-1,1 +415,nsIMIMEInfo,{1c21acef-c7a1-40c6-9d40-a20480ee53a1},0,-1,1 +416,nsIEditorLogging,{4805e681-49b9-11d3-9ce4-ed60bd6cb5bc},0,-1,1 +417,nsIIdentityInfo,{e9da87b8-b87c-4bd1-a6bc-5a9a2c7f6d8d},0,-1,1 +418,nsITransferable,{8b5314bc-db01-11d2-96ce-0060b0fb9956},0,-1,1 +419,nsIDOMNSEventTarget,{37ca0054-c715-42df-83c7-35c69e24a632},0,-1,1 +420,nsIEditingSession,{274cd32e-3675-47e1-9d8a-fc6504ded9ce},0,-1,1 +421,nsIDOMHTMLDocument,{a6cf9084-15b3-11d2-932e-00805f8add32},0,-1,1 +422,nsIStyleSheetService,{1f42a6a2-ab0a-45d4-8a96-396f58ea6c6d},0,-1,1 +423,nsIUrlClassifierUtils,{e4f0e59c-b922-48b0-a7b6-1735c1f96fed},0,-1,1 +424,nsIDOMSVGFESpecularLightingElement,{49c38287-a7c2-4895-a630-86d2b45df23c},0,-1,1 +425,nsIUrlListManager,{9c5598ec-9986-40cf-af40-b5e0d817a3a0},0,-1,1 +426,nsIDOMStorageWindow,{a44581fe-dd9b-4fd7-9893-00c4ab43f12e},0,-1,1 +427,imgIRequest,{a297d3fa-5e0c-4e59-9f30-a01c9d4f3f8b},0,-1,1 +428,nsILocaleService,{c2edc848-4219-4440-abbf-98119882c83f},0,-1,1 +429,nsIPluginDocument,{e4be1d0a-9f24-4d69-bec5-245726ab85fb},0,-1,0 +430,nsIRDFCompositeDataSource,{96343820-307c-11d2-bc15-00805f912fe7},0,-1,1 +431,nsIRequestObserver,{fd91e2e0-1481-11d3-9333-00104ba0fd40},0,-1,1 +432,nsIDOMSVGFEComponentTransferElement,{4de6b44a-f909-4948-bc43-5ee2ca6de55b},0,-1,1 +433,nsIRecyclingAllocator,{d064a04c-9cee-4319-be31-64d565bccba9},0,-1,1 +434,nsISelectionController,{b5c3ffc4-f48a-4f25-86e1-4cf79db1bcbb},0,-1,1 +435,nsIDOMSVGStylable,{ea8a6cb1-9176-45db-989d-d0e89f563d7e},0,-1,1 +436,nsIDOMHTMLIFrameElement,{a6cf90ba-15b3-11d2-932e-00805f8add32},0,-1,1 +437,nsIHttpAuthManager,{7ce8e9d1-8b4b-4883-a307-66fe12a50153},0,-1,1 +438,nsIXULBrowserWindow,{67a601df-f091-4894-a2e2-2e6cfebb35ea},0,-1,1 +439,nsIDOMSVGPointList,{4c12af24-0fc2-4fe7-b71d-5d6b41d463c1},0,-1,1 +440,nsIUserInfo,{6c1034f0-1dd2-11b2-aa14-e6657ed7bb0b},0,-1,1 +441,nsIDOMHTMLVideoElement,{edf468dc-42eb-4494-920b-56a315172640},0,-1,1 +442,nsICacheEntryDescriptor,{49c1a11d-f5d2-4f09-8262-551e64908ada},0,-1,1 +443,nsIHTMLAbsPosEditor,{91375f52-20e6-4757-9835-eb04fabe5498},0,-1,1 +444,nsIAutoCompleteObserver,{18c36504-9a4c-4ac3-8494-bd05e00ae27f},0,-1,1 +445,nsIFormHistory2,{5d7d84d1-9798-4016-bf61-a32acf09b29d},0,-1,1 +446,nsISecurityWarningDialogs,{1c399d06-1dd2-11b2-bc58-c87cbcacdb78},0,-1,1 +447,nsIImageDocument,{7b80eebc-c98e-4461-8bdb-6e3b6e828890},0,-1,1 +448,jsdIDebuggerService,{dc0a24db-f8ac-4889-80d0-6016545a2dda},0,-1,1 +449,nsITransport,{d8786c64-eb49-4a0b-b42c-0936a745fbe8},0,-1,1 +450,nsIMutable,{321578d0-03c1-4d95-8821-021ac612d18d},0,-1,1 +451,jsdICallHook,{191d2738-22e8-4756-b366-6c878c87d73b},0,-1,1 +452,nsIListBoxObject,{aa9def4e-2e59-412d-a6df-b76f52167795},0,-1,1 +453,nsIAccessibleScrollType,{05cd38b1-94b3-4cdf-8371-3935a9611405},0,-1,1 +454,nsICategoryManager,{3275b2cd-af6d-429a-80d7-f0c5120342ac},0,-1,1 +455,nsIBidirectionalIterator,{948defaa-1dd1-11b2-89f6-8ce81f5ebda9},0,-1,1 +456,nsIDOMDOMTokenList,{c6f1e160-eeeb-404a-98b0-6f1246520b6e},0,-1,1 +457,nsIURIClassifier,{2de5c563-1203-43dd-a212-f5d56d530b6f},0,-1,1 +458,nsIWindowMediatorListener,{2f276982-0d60-4377-a595-d350ba516395},0,-1,1 +459,nsISHistoryListener,{3b07f591-e8e1-11d4-9882-00c04fa02f40},0,-1,1 +460,nsIEditor,{96b60ba0-634a-41e4-928e-78ab0b3c4b46},0,-1,1 +461,nsIDOMHistory,{896d1d20-b4c4-11d2-bd93-00805f8ae3f4},0,-1,1 +462,nsIZipEntry,{e1c028bc-c478-11da-95a8-00e08161165f},0,-1,1 +463,nsIWebContentHandlerRegistrar,{e6a75410-c93e-42bf-84ca-a5c3ec34a2f1},0,-1,1 +464,mozIStorageStatementWrapper,{eee6f7c9-5586-4eaf-b35c-dca987c4ffd1},0,-1,1 +465,nsIDOMNodeList,{a6cf907d-15b3-11d2-932e-00805f8add32},0,-1,1 +466,nsIUnicharInputStream,{d5e3bd80-6723-4b92-b0c9-22f6162fd94f},0,-1,1 +467,rdfITripleVisitor,{aafea151-c271-4505-9978-a100d292800c},0,-1,1 +468,nsIDOMDOMImplementationLS,{e2c8b03c-a49a-4923-81b0-ba9a86da0e21},0,-1,1 +469,nsIDOMAbstractView,{f51ebade-8b1a-11d3-aae7-0010830123b4},0,-1,1 +470,nsIPopupBoxObject,{a41af368-9f73-4d73-a058-49dd7e41f9ea},0,-1,1 +471,nsIWorkerErrorEvent,{73d82c1d-05de-49c9-a23b-7121ff09a67a},0,-1,1 +472,nsIDOMXULSelectControlElement,{919d9808-8937-4cec-9390-91225eb8864b},0,-1,1 +473,nsIRDFLiteral,{e0c493d2-9542-11d2-8eb8-00805f29f370},0,-1,1 +474,nsIAccessible,{c81d8f8c-8585-4094-bc7c-71dd01494906},0,-1,1 +475,nsIDOMCanvasPattern,{21dea65c-5c08-4eb1-ac82-81fe95be77b8},0,-1,1 +476,nsIStreamBufferAccess,{ac923b72-ac87-4892-ac7a-ca385d429435},0,-1,0 +477,nsISupportsVoid,{464484f0-568d-11d3-baf8-00805f8a5dd7},0,-1,1 +478,nsIDOMCSSImportRule,{a6cf90cf-15b3-11d2-932e-00805f8add32},0,-1,1 +479,nsIDOMScrollAreaEvent,{b2f49035-4a2f-4e62-8fb0-deb68b0de4d9},0,-1,1 +480,jsdIContextEnumerator,{d96af02e-3379-4db5-885d-fee28d178701},0,-1,1 +481,nsIConsoleMessage,{41bd8784-1dd2-11b2-9553-8606958fffe1},0,-1,1 +482,imgILoad,{e6273acc-1dd1-11b2-a08b-824ad1b1628d},0,-1,1 +483,nsISAXLocator,{7a307c6c-6cc9-11da-be43-001422106990},0,-1,1 +484,nsIDOMHTMLSourceElement,{be281029-7dd9-4268-963e-96f5196acc19},0,-1,1 +485,nsIDOMSVGMaskElement,{fdd7039c-35b6-465a-b7a3-c98a815b583e},0,-1,1 +486,nsICookiePromptService,{72f8bb14-2810-4f38-8d0d-290c5401f54e},0,-1,1 +487,extIApplication,{e53d6610-7468-11dd-ad8b-0800200c9a66},0,-1,1 +488,nsIDOMHTMLCollection,{a6cf9083-15b3-11d2-932e-00805f8add32},0,-1,1 +489,nsIFeedPerson,{29cbd45f-f2d3-4b28-b557-3ab7a61ecde4},0,-1,1 +490,mozIStorageFunction,{9ff02465-21cb-49f3-b975-7d5b38ceec73},0,-1,1 +491,nsINavHistoryService,{437f539b-d541-4a0f-a200-6f9a6d45cce2},0,-1,1 +492,nsIDOMHTMLBRElement,{a6cf90a5-15b3-11d2-932e-00805f8add32},0,-1,1 +493,nsINonBlockingAlertService,{e800ef97-ae37-46b7-a46c-31fbe79657ea},0,-1,1 +494,nsICertificateDialogs,{a03ca940-09be-11d5-ac5d-000064657374},0,-1,1 +495,nsIInputIterator,{85585e12-1dd2-11b2-a930-f6929058269a},0,-1,1 +496,nsIGlobalHistory,{9491c383-e3c4-11d2-bdbe-0050040a9b44},0,-1,1 +497,mozIStorageStatementParams,{e65fe6e2-2643-463c-97e2-27665efe2386},0,-1,1 +498,fuelIWindow,{207edb28-eb5e-424e-a862-b0e97c8de866},0,-1,1 +499,nsIPref,{a22ad7b0-ca86-11d1-a9a4-00805f8a7ac4},0,-1,1 +500,nsIAsyncStreamCopier,{5a19ca27-e041-4aca-8287-eb248d4c50c0},0,-1,1 +501,nsIDOMSVGPathSegLinetoAbs,{5c7ba7b0-c7c5-4a7b-bc1c-2d784153be77},0,-1,1 +502,nsIDOMSVGAnimatedEnumeration,{73b101bd-797b-470f-9308-c24c64278bcd},0,-1,1 +503,nsIAutoCompleteSearch,{de8db85f-c1de-4d87-94ba-7844890f91fe},0,-1,1 +504,nsITimerCallback,{a796816d-7d47-4348-9ab8-c7aeb3216a7d},0,-1,1 +505,nsIDOMComment,{a6cf9073-15b3-11d2-932e-00805f8add32},0,-1,1 +506,nsISecretDecoderRingConfig,{01d8c0f0-0ccc-11d4-9fdd-000064657374},0,-1,1 +507,nsIXULTreeBuilderObserver,{57ced9a7-ec0b-4a0e-8aeb-5da32ebe951c},0,-1,1 +508,nsIXPTLoader,{368a15d9-17a9-4c2b-ac3d-a35b3a22b876},0,-1,1 +509,nsIContentFilter,{c18c49a8-62f0-4045-9884-4aa91e388f14},0,-1,1 +510,nsIASN1Tree,{c727b2f2-1dd1-11b2-95df-f63c15b4cd35},0,-1,1 +511,nsIHttpAuthenticator_1_9_2,{923e7c35-6e0c-448c-81a1-39c93db597d9},0,-1,1 +512,extISessionStorage,{0787ac44-29b9-4889-b97f-13573aec6971},0,-1,1 +513,nsIComponentManagerObsolete,{8458a740-d5dc-11d2-92fb-00e09805570f},0,-1,1 +514,mozIStorageStatementRow,{02eeaf95-c3db-4182-9340-222c29f68f02},0,-1,1 +515,nsIInterfaceInfo,{215dbe04-94a7-11d2-ba58-00805f8a5dd7},0,-1,0 +516,nsIShellService,{bb477da4-dddf-4106-a562-f06c85c7f9a8},0,-1,1 +517,mozISpellCheckingEngine,{43987f7b-0faa-4019-811e-42becac73fc5},0,-1,1 +518,nsIApplicationCacheContainer,{bbb80700-1f7f-4258-aff4-1743cc5a7d23},0,-1,1 +519,nsISound,{86b75b05-db60-4c3e-97a7-82b363a41a01},0,-1,1 +520,nsIJSContextStack,{c67d8270-3189-11d3-9885-006008962422},0,-1,0 +521,nsIWindowCreator2,{f673ec81-a4b0-11d6-964b-eb5a2bf216fc},0,-1,1 +522,nsIDOMNSHTMLFrameElement,{d67bd267-f984-4993-b378-95851b71f0a3},0,-1,1 +523,nsIProfile,{02b0625a-e7f3-11d2-9f5a-006008a6efe9},0,-1,1 +524,nsIDOMSVGPathSegMovetoRel,{58ca7e86-661a-473a-96de-89682e7e24d6},0,-1,1 +525,nsISystemProxySettings,{a9f3ae38-b769-4e0b-9317-578388e326c9},0,-1,1 +526,nsIPromptService,{1630c61a-325e-49ca-8759-a31b16c47aa5},0,-1,1 +527,nsIJARProtocolHandler,{92c3b42c-98c4-11d3-8cd9-0060b0fc14a3},0,-1,1 +528,nsIRefreshURI,{cb0ad623-6b46-4c09-a473-c1d6ca63d3c7},0,-1,1 +529,nsIDOMAttr,{a6cf9070-15b3-11d2-932e-00805f8add32},0,-1,1 +530,nsIDOMXPathExpression,{75506f82-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +531,nsIVariant,{6c9eb060-8c6a-11d5-90f3-0010a4e73d9a},0,-1,1 +532,nsIDOMSVGAnimatedBoolean,{7e325385-cc82-4763-bd14-e2c92edd5462},0,-1,1 +533,jsdIFilterEnumerator,{e391ba85-9379-4762-b387-558e38db730f},0,-1,1 +534,nsITreeColumn,{ae835ecf-6b32-4660-9b43-8a270df56e02},0,-1,1 +535,nsIAutoCompletePopup,{1b9d7d8a-6dd0-11dc-8314-0800200c9a66},0,-1,1 +536,nsIAccessibleCaretMoveEvent,{b9076dce-4cd3-4e3d-a7f6-7f33a7f40c31},0,-1,1 +537,nsIContentPrefService,{ea7d29eb-7095-476e-b5d9-13263f3ae243},0,-1,1 +538,nsIDOMNSCSS2Properties,{8c31e4a6-8f3a-4bb9-b180-8385ac2a4080},0,-1,1 +539,nsIDOMPkcs11,{9fd42950-25e7-11d4-8a7d-006008c844c3},0,-1,1 +540,nsIDocumentEncoderNodeFixup,{c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d},0,-1,1 +541,nsIToolkitProfile,{7422b090-4a86-4407-972e-75468a625388},0,-1,1 +542,nsIWebBrowserPrint,{9a7ca4b0-fbba-11d4-a869-00105a183419},0,-1,1 +543,nsIDOMNameList,{faaf1b80-1ddd-11d9-8c46-000a95dc234c},0,-1,1 +544,nsIGlobalHistory2,{cf777d42-1270-4b34-be7b-2931c93feda5},0,-1,1 +545,rdfIDataSource,{ebce86bd-1568-4a34-a808-9ccf9cde8087},0,-1,1 +546,nsIWebBrowserFindInFrames,{e0f5d182-34bc-11d5-be5b-b760676c6ebc},0,-1,1 +547,nsIDynamicContainer,{7e85d97b-4109-4ea7-afd8-bc2cd3840d70},0,-1,1 +548,nsISAXXMLFilter,{77a22cf0-6cdf-11da-be43-001422106990},0,-1,1 +549,nsINavHistoryFullVisitResultNode,{c49fd9d5-56e2-43eb-932c-f933f28cba85},0,-1,1 +550,nsIAddonSearchResult,{a549a714-2ada-4bb9-8a47-be26e73d49a5},0,-1,1 +551,nsIDirIndexListener,{fae4e9a8-1dd1-11b2-b53c-8f3aa1bbf8f5},0,-1,1 +552,nsISAXContentHandler,{2a99c757-dfee-4806-bff3-f721440412e0},0,-1,1 +553,nsIExternalHelperAppService,{9e456297-ba3e-42b1-92bd-b7db014268cb},0,-1,1 +554,nsIDOMSVGTitleElement,{524564b0-13a3-459b-bbec-ad66aea9f789},0,-1,1 +555,nsISocketProvider,{00b3df92-e830-11d8-d48e-0004e22243f8},0,-1,1 +556,nsIThreadObserver,{81d0b509-f198-4417-8020-08eb4271491f},0,-1,1 +557,nsIStringInputStream,{450cd2d4-f0fd-424d-b365-b1251f80fd53},0,-1,1 +558,nsIPhonetic,{bc6ea726-ab56-46b6-a21a-aa7b76d6818f},0,-1,1 +559,nsIDOMLoadStatus,{2cb53a8a-d2f4-4ddf-874f-3bc2d595c41a},0,-1,1 +560,nsIXPCScriptNotify,{b804504d-0025-4d6b-8ced-d94e41102a7f},0,-1,0 +561,nsIInterfaceInfoSuperManager,{0ee22850-bc6a-11d5-9134-0010a4e73d9a},0,-1,0 +562,nsIObjectLoadingContent_MOZILLA_1_9_2_BRANCH,{2725a137-db4b-4e43-a096-a084aeaa8b0b},0,-1,1 +563,nsIDOMCSSValue,{009f7ea5-9e80-41be-b008-db62f10823f2},0,-1,1 +564,nsICookieAcceptDialog,{3f2f0d2c-bdea-4b5a-afc6-fcf18f66b97e},0,-1,1 +565,nsIDOMSVGFEBlendElement,{8f4daf4c-de2d-450f-a373-449ad62e3800},0,-1,1 +566,nsIMenuBoxObject,{f5099746-5049-4e81-a03e-945d5110fee2},0,-1,1 +567,nsIDOMSVGFEFuncRElement,{85719a5d-9688-4c5f-bad5-c21847515200},0,-1,1 +568,nsIDOMNSEvent,{9be8096b-f795-4045-9664-0c275f36fe5b},0,-1,1 +569,nsIDOMSVGPathSegClosePath,{4970505f-2cc0-4afa-92e6-0cf4bdbf5a53},0,-1,1 +570,nsIDOMLSException,{1cc8e4b3-1dbb-4adc-a913-1527bf67748c},0,-1,1 +571,nsIDOMHTMLTimeRanges,{5c9995a1-9fce-44e8-aa7f-de52ff4c3f46},0,-1,1 +572,nsIDOMSVGFEGaussianBlurElement,{43ff8d42-3380-4dbd-a916-7c2daa3ed7f4},0,-1,1 +573,nsIDOMHTMLFieldSetElement,{a6cf9097-15b3-11d2-932e-00805f8add32},0,-1,1 +574,nsIDOMSVGLinearGradientElement,{7e15fce5-b208-43e1-952a-c570ebad0619},0,-1,1 +575,nsIDOMStorage,{43e5edad-1e02-42c4-9d99-c3d9dee22a20},0,-1,1 +576,nsIStreamLoader,{8ea7e890-8211-11d9-8bde-f66bad1e3f3a},0,-1,1 +577,nsIDOMWindowCollection,{a6cf906f-15b3-11d2-932e-00805f8add32},0,-1,1 +578,nsIBinaryInputStream,{7b456cb0-8772-11d3-90cf-0040056a906e},0,-1,1 +579,nsIDOMSVGFEConvolveMatrixElement,{42109b58-a8c1-4078-b44c-ec1d5d6b9574},0,-1,1 +580,nsISSLStatus,{cfede939-def1-49be-81ed-d401b3a07d1c},0,-1,1 +581,nsITextScroll,{067b28a0-877f-11d3-af7e-00a024ffc08c},0,-1,1 +582,nsIDOMSVGRadialGradientElement,{d0262ae1-31a4-44be-b82e-85e4cfe280fd},0,-1,1 +583,nsIBidirectionalEnumerator,{75f158a0-cadd-11d2-8cca-0060b0fc14a3},0,-1,0 +584,nsIVersionComparator,{e6cd620a-edbb-41d2-9e42-9a2ffc8107f3},0,-1,1 +585,nsIUrlClassifierLookupCallback,{f1dc83c6-ad43-4f0f-a809-fd43de7de8a4},0,-1,0 +586,nsIControllerCommandTable,{d1a47834-6ad4-11d7-bfad-000393636592},0,-1,1 +587,nsIWindowWatcher,{002286a8-494b-43b3-8ddd-49e3fc50622b},0,-1,1 +588,nsIDOMXPathException,{75506f89-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +589,nsIDOMXULCommandEvent,{f9fa8205-a988-4828-9228-f3332d5475ac},0,-1,1 +590,nsISHistory,{9883609f-cdd8-4d83-9b55-868ff08ad433},0,-1,1 +591,nsIAutoCompleteBaseResult,{e6396544-921d-4776-aa62-8bf2dc1ae058},0,-1,0 +592,nsIDOMCrypto,{12b6d899-2aed-4ea9-8c02-2223ab7ab592},0,-1,1 +593,nsIDOMSVGFEDiffuseLightingElement,{2e9eb422-2398-4be9-a9b8-b1cc7aa9dd6f},0,-1,1 +594,nsIWorkerLocation,{17a005c3-4f2f-4bb6-b169-c181fa6873de},0,-1,1 +595,nsISimpleUnicharStreamFactory,{8238cd2e-e8e3-43e8-b556-56e21389c766},0,-1,1 +596,nsIDOMMutationEvent,{8e440d86-886a-4e76-9e59-c13b939c9a4b},0,-1,1 +597,nsIDOMSVGTextPositioningElement,{5d052835-8cb0-442c-9754-a8e616db1f89},0,-1,1 +598,nsIDOMSVGPathSegArcAbs,{c9e222e5-31fd-4083-ae1f-fcf013681340},0,-1,1 +599,nsIDOMNSHTMLAnchorElement,{a6cf911c-15b3-11d2-932e-00805f8add32},0,-1,1 +600,nsILocalHandlerApp,{9812be73-273c-478c-8170-c3e0db08ae7c},0,-1,1 +601,nsIComponentRegistrar,{2417cbfe-65ad-48a6-b4b6-eb84db174392},0,-1,1 +602,nsIFileChannel,{06169120-136d-45a5-b535-498f1f755ab7},0,-1,1 +603,nsIPluginHost,{30c7c529-b05c-4950-b5b8-9af673e46521},0,-1,1 +604,nsIDOMSVGPathElement,{2b19e692-3338-440f-a998-3cb1e8474999},0,-1,1 +605,nsIHttpAuthenticator,{0f331436-8bc8-4c68-a124-d0253a19d06f},0,-1,1 +606,nsIPlugin,{0937fb08-16e8-4365-babf-88e09e4e33a4},0,-1,0 +607,nsICacheListener,{638c3848-778b-4851-8ff3-9400f65b8773},0,-1,1 +608,mozIStorageResultSet,{18dd7953-076d-4598-8105-3e32ad26ab24},0,-1,1 +609,mozIStorageValueArray,{07b5b93e-113c-4150-863c-d247b003a55d},0,-1,1 +610,nsIStreamCipher,{1d507cd6-1630-4710-af1b-4012dbcc514c},0,-1,1 +611,nsIProtocolProxyService2,{dbd9565d-29b1-437a-bff5-2fc339e2c5df},0,-1,1 +612,nsIDOMDocumentEvent,{46b91d66-28e2-11d4-ab1e-0010830123b4},0,-1,1 +613,nsICMSMessageErrors,{f2aec680-60a0-49f0-afe5-6cf1d3f15e0d},0,-1,1 +614,nsICrashReporter,{44650737-59f7-4c9b-adbe-2b6d4dfee86a},0,-1,1 +615,nsIXULAppInfo,{a61ede2a-ef09-11d9-a5ce-001124787b2e},0,-1,1 +616,nsIProxiedProtocolHandler,{0a24fed4-1dd2-11b2-a75c-9f8b9a8f9ba7},0,-1,1 +617,nsISupportsString,{d79dc970-4a1c-11d3-9890-006008962422},0,-1,1 +618,nsIDOMNSFeatureFactory,{dc5ba787-b648-4b01-a8e7-b293ffb044ef},0,-1,1 +619,nsISafeOutputStream,{5f914307-5c34-4e1f-8e32-ec749d25b27a},0,-1,1 +620,inIDeepTreeWalker,{91fca0e9-99d6-406b-9d78-4c96f11e9ee4},0,-1,1 +621,nsIComponentManager,{a88e5a60-205a-4bb1-94e1-2628daf51eae},0,-1,1 +622,nsIDocShellTreeItem,{09b54ec1-d98a-49a9-bc95-3219e8b55089},0,-1,1 +623,nsIDOMCSSFontFaceRule,{a6cf90bb-15b3-11d2-932e-00805f8add32},0,-1,1 +624,nsIPrincipal,{b8268b9a-2403-44ed-81e3-614075c92034},0,-1,1 +625,nsIAlertsService,{e177399e-2e31-4019-aed3-cba63ce9fa99},0,-1,1 +626,nsITaggingService,{e39cea60-7e6d-4c8b-80a3-997af1c2cbcb},0,-1,1 +627,nsIXMLHttpRequestEventTarget,{6ce0a193-b033-4c3d-b748-f851b09261f5},0,-1,1 +628,nsICMSMessage2,{a99a3203-39e3-45e1-909c-175b0e471c2b},0,-1,0 +629,nsIAutoCompleteMdbResult,{f7e7b341-2d5c-4d04-9f51-496cb2ce178c},0,-1,0 +630,nsIPrefBranch2,{74567534-eb94-4b1c-8f45-389643bfc555},0,-1,1 +631,nsIDOMDragEvent,{d52cf140-fb90-44df-8d69-4b2bab4d461f},0,-1,1 +632,inISearchObserver,{46226d9b-e398-4106-8d9b-225d4d0589f5},0,-1,1 +633,nsIDOMSVGAnimatedLength,{a52f0322-7f4d-418d-af6d-a7b14abd5cdf},0,-1,1 +634,nsIPasswordManager,{173562f0-2173-11d5-a54c-0010a401eb10},0,-1,1 +635,nsISupportsID,{d18290a0-4a1c-11d3-9890-006008962422},0,-1,1 +636,nsIRollupListener,{0ca103e5-80d4-4b81-a310-be0708f8eaa9},0,-1,0 +637,nsIResProtocolHandler,{067ca872-e947-4bd6-8946-a479cb6ba5dd},0,-1,1 +638,nsIServerSocketListener,{836d98ec-fee2-4bde-b609-abd5e966eabd},0,-1,1 +639,nsIAccessNode,{71a3b4e7-e83d-45cf-a20e-9ce292bcf19f},0,-1,1 +640,nsIDOMSVGPathSegCurvetoQuadraticAbs,{b7aef0f0-2830-4145-b04f-fe05789ccf8a},0,-1,1 +641,nsIWebNavigation,{f5d9e7b0-d930-11d3-b057-00a024ffc08c},0,-1,1 +642,nsISupportsPRInt64,{e3cb0ff0-4a1c-11d3-9890-006008962422},0,-1,1 +643,nsIXPCComponents_ID,{7994a6e0-e028-11d3-8f5d-0010a4e73d9a},0,-1,1 +644,nsITooltipTextProvider,{b128a1e6-44f3-4331-8fbe-5af360ff21ee},0,-1,1 +645,nsIXPCComponents_Classes,{978ff520-d26c-11d2-9842-006008962422},0,-1,1 +646,nsIFastLoadService,{759e475e-0c23-4dbf-b1b8-78c9369e3072},0,-1,1 +647,jsdIProperty,{4491ecd4-fb6b-43fb-bd6f-5d1473f1df24},0,-1,1 +648,nsIDOMHTMLDListElement,{a6cf909b-15b3-11d2-932e-00805f8add32},0,-1,1 +649,nsIWorkerGlobalScope,{c111e7d3-8044-4458-aa7b-637696ffb841},0,-1,1 +650,nsIDOMHTMLLegendElement,{a6cf9098-15b3-11d2-932e-00805f8add32},0,-1,1 +651,nsIAutoConfig,{80db54ae-13f2-11d5-be44-00108335a220},0,-1,0 +652,nsIDOMNSHTMLAreaElement2,{1859b16a-7c16-4ab7-bdb9-52792ba16cc1},0,-1,1 +653,nsIDOMSVGDefsElement,{a2e86036-f04c-4013-9f74-e7090a0aac0a},0,-1,1 +654,nsIBaseWindow,{046bc8a0-8015-11d3-af70-00a024ffc08c},0,-1,1 +655,nsIFastLoadFileControl,{8a1e2c63-af50-4147-af7e-26289dc180dd},0,-1,1 +656,nsIPrefService,{decb9cc7-c08f-4ea5-be91-a8fc637ce2d2},0,-1,1 +657,nsIDOMLSProgressEvent,{b9a2371f-70e9-4657-b0e8-28e15b40857e},0,-1,1 +658,nsIMicrosummaryGenerator,{05b48344-d0a7-427e-934e-9a6e0d5ecced},0,-1,1 +659,mozIStorageRow,{62d1b6bd-cbfe-4f9b-aee1-0ead4af4e6dc},0,-1,1 +660,nsIDOMGeoPosition,{23e5269f-4dd7-41c4-b52a-75918694c2de},0,-1,1 +661,nsIDOMSVGPathSeg,{b9022da7-e26d-4df3-8c94-b45c4aedda7c},0,-1,1 +662,fuelIBrowserTab,{3073ceff-777c-41ce-9ace-ab37268147c1},0,-1,1 +663,nsISSLCertErrorDialog,{0729ce8e-8935-4989-ba72-a2d6307f2365},0,-1,1 +664,nsIThreadJSContextStack,{a1339ae0-05c1-11d4-8f92-0010a4e73d9a},0,-1,0 +665,nsIScriptChannel,{33234b99-9588-4c7d-9da6-86b8b7cba565},0,-1,1 +666,nsIDOMBarProp,{9eb2c150-1d56-11d3-8221-0060083a0bcf},0,-1,1 +667,nsIPluginInstanceOwner,{c4ed03f3-498b-4045-97c7-0b05838f886c},0,-1,0 +668,nsIDOMStorageList,{a4e9b257-5ccf-4b17-8721-23ac45c83128},0,-1,1 +669,nsIHttpHeaderVisitor,{0cf40717-d7c1-4a94-8c1e-d6c9734101bb},0,-1,1 +670,fuelIAnnotations,{335c9292-91a1-4ca0-ad0b-07d5f63ed6cd},0,-1,1 +671,nsIWindowProvider,{5119ac7f-81dd-4061-96a7-71f2cf5efee4},0,-1,1 +672,nsIPrintSettingsService,{841387c8-72e6-484b-9296-bf6eea80d58a},0,-1,1 +673,nsIDOMSVGFEColorMatrixElement,{0e966878-ebf1-4455-86fd-f4c7b1f24777},0,-1,1 +674,nsIPKCS11,{5743f870-958e-4f02-aef2-c0afeef67f05},0,-1,1 +675,nsIDOMSVGFEFuncAElement,{fa48511c-283a-437f-9507-c309ac6f0f57},0,-1,1 +676,nsIObjectInputStream,{6c248606-4eae-46fa-9df0-ba58502368eb},0,-1,1 +677,nsIDOMSVGFETileElement,{ed042a81-39fc-4c89-9385-75758a2434b5},0,-1,1 +678,nsIDOMGetSVGDocument,{b5d3074c-4f63-4936-bf39-49034efa26a5},0,-1,1 +679,nsIDirIndex,{23bbabd0-1dd2-11b2-86b7-aad68ae7d7e0},0,-1,1 +680,nsIPasswordManagerInternal,{a448531f-dc92-4dc1-9012-da841febcbe0},0,-1,1 +681,nsIDOMNSHTMLHRElement,{19b5879f-c125-447c-aaaf-719de3ef221a},0,-1,1 +682,nsIDOMSVGFEFloodElement,{2743af95-28c5-429d-9812-12b7b017887e},0,-1,1 +683,nsIFormFillController,{07f0a0dc-f6e9-4cdd-a55f-56d770523a4c},0,-1,1 +684,nsIRecentBadCertsService,{a5ae8b05-a76e-408f-b0ba-02a831265749},0,-1,1 +685,nsICommandHandler,{34a4fcf0-66fc-11d4-9528-0020183bf181},0,-1,1 +686,nsIDOMHTMLObjectElement,{a6cf90ac-15b3-11d2-932e-00805f8add32},0,-1,1 +687,nsIDOMLocation,{a6cf906d-15b3-11d2-932e-00805f8add32},0,-1,1 +688,nsIViewSourceChannel,{8b77d6e2-2ae9-11d5-be57-000064657374},0,-1,0 +689,nsISyncLoadDOMService,{8095998d-ae1c-4cfa-9b43-0973e5d77eb0},0,-1,1 +690,nsIDOMXULDescriptionElement,{c7b0b43c-1dd1-11b2-9e1c-ce5f6a660630},0,-1,1 +691,nsIURL,{d6116970-8034-11d3-9399-00104ba0fd40},0,-1,1 +692,nsIMultiplexInputStream,{a076fd12-1dd1-11b2-b19a-d53b5dffaade},0,-1,1 +693,nsIQueryContentEventResult,{4b4ba266-b51e-4f0f-8d0e-9f13cb2a0056},0,-1,1 +694,nsIThreadEventFilter,{a0605c0b-17f5-4681-b8cd-a1cd75d42559},0,-1,1 +695,nsIXPCSecurityManager,{31431440-f1ce-11d2-985a-006008962422},0,-1,0 +696,nsIDOMXULMenuListElement,{3d49950e-04f9-4e35-a9a0-ffd51356a674},0,-1,1 +697,nsIDocShellTreeNode,{37f1ab73-f224-44b1-82f0-d2834ab1cec0},0,-1,1 +698,nsIWebBrowserChrome,{ba434c60-9d52-11d3-afb0-00a024ffc08c},0,-1,1 +699,nsIFastLoadWriteControl,{2ad6e9e6-1379-4e45-a899-a54b27ff915c},0,-1,1 +700,nsITreeView,{c06dc4d3-63a2-4422-a0a3-5f2eddeca8c1},0,-1,1 +701,nsIHandlerApp,{8d298761-0963-4c90-99e2-6ea498825e82},0,-1,1 +702,nsIByteRangeRequest,{c1b1f426-7e83-4759-9f88-0e1b17f49366},0,-1,1 +703,nsIPrintStatusFeedback,{19855dff-3248-4902-b196-93ee4c477880},0,-1,1 +704,nsINetUtil,{a50d5516-5c0a-4f08-b427-703ca0c44ac3},0,-1,1 +705,nsPIPlacesDatabase,{8e6d4f8a-4b8e-4026-9fca-517c4494ddb7},0,-1,1 +706,nsIDOMRange,{a6cf90ce-15b3-11d2-932e-00805f8add32},0,-1,1 +707,nsIAccessibleStates,{7fe1ee90-edaa-43f1-9f3b-071099b51f08},0,-1,1 +708,nsIAtomService,{9c1f50b9-f9eb-42d4-a8cb-2c7600aeb241},0,-1,1 +709,nsIExceptionProvider,{0577744c-c1d2-47f2-8bcc-ce7a9e5a88fc},0,-1,1 +710,nsIDOMJSNavigator,{4b4f8316-1dd2-11b2-b265-9a857376d159},0,-1,1 +711,nsIScriptableDateFormat,{0c89efb0-1aae-11d3-9141-006008a6edf6},0,-1,1 +712,nsIDOM3EventTarget,{3e9c01a7-de97-4c3b-8294-b4bd9d7056d1},0,-1,1 +713,nsIDOMSVGAnimatedAngle,{c6ab8b9e-32db-464a-ae33-8691d44bc60a},0,-1,1 +714,nsIDOMXPathNSResolver,{75506f83-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +715,nsIFTPChannel,{2315d831-8b40-446a-9138-fe09ebb1b720},0,-1,1 +716,nsIDOMCSSValueList,{8f09fa84-39b9-4dca-9b2f-db0eeb186286},0,-1,1 +717,nsIStackFrame,{91d82105-7c62-4f8b-9779-154277c0ee90},0,-1,1 +718,nsIDOMHTMLFontElement,{a6cf90a7-15b3-11d2-932e-00805f8add32},0,-1,1 +719,nsIEffectiveTLDService,{6852369e-baa9-4c9a-bbcd-5123fc54a297},0,-1,1 +720,imgIEncoder,{ba3a854b-fb8d-4881-8af9-5849df10e5e5},0,-1,1 +721,nsIToolkitChromeRegistry,{8727651c-9530-45a0-b81e-0e0690c30c50},0,-1,1 +722,nsIDOMSVGPathSegCurvetoQuadraticSmoothRel,{ac0b2007-04e4-4e70-a0e0-294f374b29c4},0,-1,1 +723,nsIPropertyBag,{bfcd37b0-a49f-11d5-910d-0010a4e73d9a},0,-1,1 +724,nsIFeedElementBase,{5215291e-fa0a-40c2-8ce7-e86cd1a1d3fa},0,-1,1 +725,nsIINIParserFactory,{ccae7ea5-1218-4b51-aecb-c2d8ecd46af9},0,-1,1 +726,nsIFormSigningDialog,{4fe04d6d-4b66-4023-a0bc-b43ce68b3e15},0,-1,1 +727,nsIDOMProgressEvent,{6af7022c-d7f8-414c-a11f-a7918f14052b},0,-1,1 +728,nsIAccessibleImage,{09086623-0f09-4310-ac56-c2cda7c29648},0,-1,1 +729,nsILiveTitleNotificationSubject,{f9e577a8-19d9-4ca0-a140-b9e43f014470},0,-1,1 +730,nsITypeAheadFind,{0749a445-19d3-4eb9-9d66-78eca8c6f604},0,-1,1 +731,nsIDOMFile_1_9_2_BRANCH,{fc41a294-8c9a-4639-b8ed-7c04f8017ef6},0,-1,1 +732,nsISSLStatusProvider,{8de811f0-1dd2-11b2-8bf1-e9aa324984b2},0,-1,1 +733,nsIProxyAutoConfig,{a42619df-0a1c-46fb-8154-0e9b8f8f1ea8},0,-1,1 +734,nsIMozIconURI,{1fb33f44-f522-4880-a225-4b75d09b04c6},0,-1,1 +735,nsIAuthPrompt2,{651395eb-8612-4876-8ac0-a88d4dce9e1e},0,-1,1 +736,nsIProfileChangeStatus,{2f977d43-5485-11d4-87e2-0010a4e75ef2},0,-1,1 +737,nsIDOMSVGComponentTransferFunctionElement,{cb615c0f-8d4a-4e30-9695-a3dd6f4216ee},0,-1,1 +738,nsISupportsArray,{791eafa0-b9e6-11d1-8031-006008159b5a},0,-1,1 +739,nsIThreadPoolListener,{ef194cab-3f86-4b61-b132-e5e96a79e5d1},0,-1,1 +740,nsIPromptFactory,{2532b748-75db-4732-9173-78d3bf34f694},0,-1,1 +741,nsIHttpActivityDistributor,{7c512cb8-582a-4625-b5b6-8639755271b5},0,-1,1 +742,nsIMemoryReporterManager,{7c62de18-1edd-40f8-9da2-a8c622763074},0,-1,1 +743,nsIWebBrowserPersist,{dd4e0a6a-210f-419a-ad85-40e8543b9465},0,-1,1 +744,nsIErrorService,{e72f94b2-5f85-11d4-9877-00c04fa0cf4a},0,-1,1 +745,nsIDOMCSSStyleSheet,{a6cf90c2-15b3-11d2-932e-00805f8add32},0,-1,1 +746,mozIPlacesAutoComplete,{a5ae8332-333c-412a-bb02-a35df8247714},0,-1,1 +747,nsIXULTemplateBuilder,{a583b676-5b02-4f9c-a0c9-cb850cb99818},0,-1,1 +748,nsIXPointerSchemeContext,{781f4aa1-ebb3-4667-b1c2-2b35e94c4281},0,-1,0 +749,nsISemanticUnitScanner,{9f620be4-e535-11d6-b254-00039310a47a},0,-1,1 +750,nsIAccessibleTableChangeEvent,{a9485c7b-5861-4695-8441-fab0235b205d},0,-1,1 +751,nsIDOMSVGTextPathElement,{5c29a76c-3489-48fe-b9ea-ea0f5b196dff},0,-1,1 +752,nsIDebug2,{9c9307ed-480a-4f2a-8f29-21378c03bcbc},0,-1,1 +753,nsIClientAuthDialogs,{fa4c7520-1433-11d5-ba24-00108303b117},0,-1,1 +754,nsIDOMBeforeUnloadEvent,{da19e9dc-dea2-4a1d-a958-9be375c9799c},0,-1,1 +755,nsIDOMNSHTMLElement,{7f142f9a-fba7-4949-93d6-cf08a974ac51},0,-1,1 +756,nsIDOMHTMLBodyElement,{a6cf908e-15b3-11d2-932e-00805f8add32},0,-1,1 +757,nsIEnumerator,{ad385286-cbc4-11d2-8cca-0060b0fc14a3},0,-1,1 +758,nsIBufferedInputStream,{616f5b48-da09-11d3-8cda-0060b0fc14a3},0,-1,1 +759,nsIX509CertList,{a539759b-e22d-462f-94ea-2915b11b33e8},0,-1,1 +760,nsICMSDecoder,{65244a06-a342-11d5-ba47-00108303b117},0,-1,0 +761,nsISMimeVerificationListener,{56310af6-dffc-48b4-abca-85eae4059064},0,-1,0 +762,nsIInputStreamChannel,{274c4d7a-2447-4ceb-a6de-80db1b83f5d2},0,-1,1 +763,nsISecurityInfoProvider,{b8cc9126-9319-4415-afd9-b82220d453ed},0,-1,1 +764,nsIDOMKeyEvent,{028e0e6e-8b01-11d3-aae7-0010838a3123},0,-1,1 +765,nsIGeolocationProvider,{701413ed-0f51-64f7-71c7-4369d8e07d6e},0,-1,1 +766,nsIDOMSVGForeignObjectElement,{fd9c9871-23fd-48eb-a65b-3842e9b0acbd},0,-1,1 +767,nsIThread,{9c889946-a73a-4af3-ae9a-ea64f7d4e3ca},0,-1,1 +768,nsICommandController,{ebe55080-c8a9-11d5-a73c-dd620d6e04bc},0,-1,1 +769,nsIIOService2,{d44fe6d4-ee35-4789-886a-eb8f0554d04e},0,-1,1 +770,nsIEditorBoxObject,{e3800a23-5b83-49aa-b18c-efa1ac5416e0},0,-1,1 +771,nsIPrintSession,{2f977d52-5485-11d4-87e2-0010a4e75ef2},0,-1,0 +772,nsIStreamTransportService,{8268d474-efbf-494f-a152-e8a8616f4e52},0,-1,1 +773,nsIDOMSVGFilterElement,{9e81d4ae-190c-4b9d-a076-ebc52a7bf231},0,-1,1 +774,nsIDownloadHistory,{202533cd-a8f1-4ee4-8d20-3a6a0d2c6c51},0,-1,1 +775,nsIDOMHTMLButtonElement,{a6cf9095-15b3-11d2-932e-00805f8add32},0,-1,1 +776,nsIDOMDataContainerEvent,{3600d66c-b9ac-4c22-b39a-d64cce619921},0,-1,1 +777,nsIDOMPaintRequestList,{01627136-fdd8-44b4-aac0-7d613608a3d4},0,-1,1 +778,nsIModuleLoader,{9b328e24-4d85-4a9c-9cb7-f25e66f430c3},0,-1,1 +779,nsIDOMNSHTMLInputElement,{2cb61f32-b21f-4b87-904c-8876d8bb5f33},0,-1,1 +780,nsIDOMSVGFEDistantLightElement,{02141672-7f2c-412a-a7d7-4caa194842e9},0,-1,1 +781,nsITransfer,{23c51569-e9a1-4a92-adeb-3723db82ef7c},0,-1,1 +782,nsIOfflineCacheUpdateObserver,{a28abeaf-a0b4-4440-b2fe-bc78249710ea},0,-1,1 +783,nsIDOMHTMLTableColElement,{a6cf90b4-15b3-11d2-932e-00805f8add32},0,-1,1 +784,nsIScriptEventManager,{b6427ace-dc77-495b-ab21-43baeb52bc27},0,-1,0 +785,mozIStorageProgressHandler,{a3a6fcd4-bf89-4208-a837-bf2a73afd30c},0,-1,1 +786,nsIDOMSVGPathSegCurvetoQuadraticRel,{c46eb661-9c05-4d46-9b2a-c2ae5b166060},0,-1,1 +787,nsIXMLHttpRequestUpload,{09ff3682-7759-4441-a765-f70e1a1fabcf},0,-1,1 +788,nsIDOMSVGTSpanElement,{4a23cb1f-cf1e-437e-9524-8756f7928b2e},0,-1,1 +789,nsIControllerContext,{47b82b60-a36f-4167-8072-6f421151ed50},0,-1,1 +790,nsIUrlClassifierStreamUpdater,{daf3038a-556c-47d3-a3d2-36caa9a762a0},0,-1,1 +791,nsIDOMSVGClipPathElement,{0c3f45a4-e6d0-44e7-a2f8-d128ecf1db9b},0,-1,1 +792,nsICertTree,{a8cd1c89-a901-4735-831b-7198b7b8b6b1},0,-1,1 +793,nsIUTF8StringEnumerator,{9bdf1010-3695-4907-95ed-83d0410ec307},0,-1,1 +794,nsIExpatSink,{f61c56b5-ea5b-42b4-ad3c-17416e72e238},0,-1,1 +795,nsIDocShell,{8adfb831-1053-4a19-884d-bcdad7277b4b},0,-1,1 +796,extIEvents,{3a8ec9d0-ab19-11db-abbd-0800200c9a66},0,-1,1 +797,nsIINIParser,{7eb955f6-3e78-4d39-b72f-c1bf12a94bce},0,-1,1 +798,nsIXBLAccessible,{3716eb86-166b-445b-a94a-9b522fee96e6},0,-1,1 +799,nsIDOMEventListener,{df31c120-ded6-11d1-bd85-00805f8ae3f4},0,-1,1 +800,nsPICertNotification,{42cd7162-ea4a-4088-9888-63ea5095869e},0,-1,0 +801,nsIPermission,{28f16d80-157b-11d5-a542-0010a401eb10},0,-1,1 +802,nsIDOMStorageObsolete,{18013cf9-b104-49cf-9484-c2a7a845457e},0,-1,1 +803,nsIEditorObserver,{a6cf9125-15b3-11d2-932e-00805f8add32},0,-1,1 +804,nsIPrefSecurityCheck,{c73c9a05-92ce-46e1-8f69-90a2a3a36104},0,-1,0 +805,nsICertVerificationListener,{6684bce9-50db-48e1-81b7-98102bf81357},0,-1,1 +806,nsIDOMMessageEvent,{98150805-6a15-4667-815a-1a8c87cb4bbc},0,-1,1 +807,nsIIOService,{bddeda3f-9020-4d12-8c70-984ee9f7935e},0,-1,1 +808,nsIDOMCanvasGradient,{bbb20a59-524e-4662-981e-5e142814b20c},0,-1,1 +809,nsIDOMEventGroup,{33347bee-6620-4841-8152-36091ae80c7e},0,-1,1 +810,nsISidebarExternal,{4350fb73-9305-41df-a669-11d26222d420},0,-1,1 +811,nsITooltipListener,{44b78386-1dd2-11b2-9ad2-e4eee2ca1916},0,-1,1 +812,nsIDOMNSHTMLTextAreaElement,{ca066b44-9ddf-11d3-bccc-0060b0fc76bd},0,-1,1 +813,nsIDOMSVGNumberList,{59364ec4-faf1-460f-bf58-e6a6a2769a3a},0,-1,1 +814,nsIAccessibleStateChangeEvent,{444db51a-05fd-4576-8a64-32dbb2a83884},0,-1,1 +815,nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs,{ff5bbb58-b49a-450f-b91b-e50585c34b3d},0,-1,1 +816,nsISAXLexicalHandler,{23c26a56-adff-440c-8caf-95c2dc2e399b},0,-1,1 +817,nsISMimeCert,{66710f97-a4dd-49f1-a906-fe0ebc5924c0},0,-1,1 +818,nsIAppShellService,{361facd0-6e9a-4ff1-a0d4-450744cf0023},0,-1,1 +819,nsIDOMSVGPathSegArcRel,{49d0360d-bb66-4ab9-b9b0-f49b93398595},0,-1,1 +820,nsILoginInfo,{c41b7dff-6b9b-42fe-b78d-113051facb05},0,-1,1 +821,nsIDOMHTMLMetaElement,{a6cf908a-15b3-11d2-932e-00805f8add32},0,-1,1 +822,nsINavHistoryResultViewer,{af4ac418-a687-4775-8ffa-97c160196432},0,-1,1 +823,nsISaveAsCharset,{33b87f70-7a9c-11d3-915c-006008a6edf6},0,-1,1 +824,nsICMSSecureMessage,{14b4394a-1dd2-11b2-b4fd-ba4a194fe97e},0,-1,1 +825,nsIStringBundleService,{d85a17c0-aa7c-11d2-9b8c-00805f8a16d9},0,-1,1 +826,nsIXULOverlayProvider,{1d5b5b94-dc47-4050-93b7-ac092e383cad},0,-1,1 +827,nsIAuthModule,{6e35dbc0-49ef-4e2c-b1ea-b72ec64450a2},0,-1,0 +828,nsICommandHandlerInit,{731c6c50-67d6-11d4-9529-0020183bf181},0,-1,1 +829,nsINavHistoryResult,{d1562f6f-8d5a-4042-8524-72f747a51b18},0,-1,1 +830,nsIDOMDOMImplementation,{a6cf9074-15b3-11d2-932e-00805f8add32},0,-1,1 +831,nsIFastLoadFileIO,{715577db-d9c5-464a-a32e-0a40c29b22d4},0,-1,1 +832,nsICollation,{b0132cc0-3786-4557-9874-910d7def5f93},0,-1,1 +833,nsIDOMLSOutput,{757e9971-8890-478d-a53a-07f9f6f6e0d3},0,-1,1 +834,nsIGConfService,{5009acae-6973-48c3-b6d6-52c692cc5d9d},0,-1,1 +835,nsIDOMSVGAnimatedNumber,{716e3b11-b03b-49f7-b82d-5383922b0ab3},0,-1,1 +836,nsIProfileStartup,{048e5ca1-0eb7-4bb1-a9a2-a36f7d4e0e3c},0,-1,1 +837,nsIUUIDGenerator,{138ad1b2-c694-41cc-b201-333ce936d8b8},0,-1,1 +838,nsIControllerCommandGroup,{9f82c404-1c7b-11d5-a73c-eca43ca836fc},0,-1,1 +839,nsIXSLTProcessor,{4a91aeb3-4100-43ee-a21e-9866268757c5},0,-1,1 +840,nsIDialogParamBlock,{f76c0901-437a-11d3-b7a0-e35db351b4bc},0,-1,1 +841,nsISessionStore,{70592a0d-87d3-459c-8db7-dcb8d47af78e},0,-1,1 +842,nsIRDFBlob,{237f85a2-1dd2-11b2-94af-8122582fc45e},0,-1,1 +843,nsIDOMHTMLHeadElement,{a6cf9087-15b3-11d2-932e-00805f8add32},0,-1,1 +844,nsIXPCComponents_Exception,{5bf039c0-e028-11d3-8f5d-0010a4e73d9a},0,-1,1 +845,nsIASN1PrintableItem,{114e1142-1dd2-11b2-ac26-b6db19d9184a},0,-1,1 +846,nsIDOMNSHTMLButtonElement,{c914d7a4-63b3-4d40-943f-91a3c7ab0d4d},0,-1,1 +847,nsIDOMHTMLMapElement,{a6cf90af-15b3-11d2-932e-00805f8add32},0,-1,1 +848,nsISupportsDouble,{b32523a0-4ac0-11d3-baea-00805f8a5dd7},0,-1,1 +849,nsICrashReporter_MOZILLA_1_9_2_BRANCH,{e8fe590f-7c08-4128-a746-57eb6b427d8f},0,-1,1 +850,nsINSSErrorsService,{3a5c7a0f-f5da-4a8b-a748-d7c5a528f33b},0,-1,1 +851,nsIProtocolProxyCallback,{a9967200-f95e-45c2-beb3-9b060d874bfd},0,-1,1 +852,nsIApplicationCache,{663e2e2e-04a0-47b6-87b3-a122be46cb53},0,-1,1 +853,nsIXULSortService,{f29270c8-3be5-4046-9b57-945a84dff132},0,-1,1 +854,nsIUploadChannel2,{8821e259-7252-4464-b874-a55d8ef6b222},0,-1,1 +855,nsIDOMNSHTMLOptionCollection,{1181207b-2337-41a7-8ddf-fbe96461256f},0,-1,1 +856,nsIXULTreeBuilder,{06b31b15-ebf5-4e74-a0e2-6bc0a18a3969},0,-1,1 +857,nsIModifyableXPointerResult,{2dc3be2e-642d-4d7e-b3c5-f3dac51afbee},0,-1,0 +858,nsIHistoryEntry,{a41661d4-1417-11d5-9882-00c04fa02f40},0,-1,1 +859,nsIBrowserDOMWindow,{f9691a49-7fb3-4b54-bb11-a4f2e0b6eddb},0,-1,1 +860,nsIDOMXULImageElement,{f73f4d77-a6fb-4ab5-b41e-15045a0cc6ff},0,-1,1 +861,nsIAnnotationObserver,{63fe98e0-6889-4c2c-ac9f-703e4bc25027},0,-1,1 +862,nsIFileURL,{d26b2e2e-1dd1-11b2-88f3-8545a7ba7949},0,-1,1 +863,nsIFindService,{5060b801-340e-11d5-be5b-b3e063ec6a3c},0,-1,1 +864,nsIContentDispatchChooser,{456ca3b2-02be-4f97-89a2-08c08d3ad88f},0,-1,1 +865,nsIHandlerInfo,{325e56a7-3762-4312-aec7-f1fcf84b4145},0,-1,1 +866,nsIDOMHTMLOptionsCollection,{bce0213c-f70f-488f-b93f-688acca55d63},0,-1,1 +867,nsIDOMHTMLTableRowElement,{a6cf90b6-15b3-11d2-932e-00805f8add32},0,-1,1 +868,nsIClipboardHelper,{44073a98-1dd2-11b2-8600-d0ae854dbe93},0,-1,1 +869,nsIWebProgressListener,{570f39d1-efd0-11d3-b093-00a024ffc08c},0,-1,1 +870,nsIReadConfig,{ba5bc4c6-1dd1-11b2-bb89-b844c6ec0339},0,-1,0 +871,nsIUrlClassifierHashCompleter,{ade9b72b-3562-44f5-aba6-e63246be53ae},0,-1,1 +872,nsIDragService,{82b58ada-f490-4c3d-b737-1057c4f1d052},0,-1,1 +873,nsIDOMSVGException,{64e6f0e1-af99-4bb9-ab25-7e56012f0021},0,-1,1 +874,nsIDOMSVGTransformable,{b81f6e37-1842-4534-a546-1ab86e59a3c6},0,-1,1 +875,nsIDOMSVGFEMorphologyElement,{16154319-fb5f-4473-b360-5065b6096d33},0,-1,1 +876,nsILocale,{21035ee0-4556-11d3-91cd-00105aa3f7dc},0,-1,1 +877,nsIClipboardCommands,{b8100c90-73be-11d2-92a5-00105a1b0d64},0,-1,1 +878,nsIUpdateItem,{f559f340-5160-420f-abc8-19b251708e7e},0,-1,1 +879,nsICiter,{a6cf9102-15b3-11d2-932e-00805f8add32},0,-1,1 +880,nsIUrlClassifierUpdateObserver,{bbb33c65-e783-476c-8db0-6ddb91826c07},0,-1,1 +881,nsIXSLTException,{e06dfaea-92d5-47f7-a800-c5f5404d8771},0,-1,1 +882,nsIFormHistoryImporter,{9e811188-6a5b-4d96-a92d-1bac66a41898},0,-1,1 +883,nsISAXDTDHandler,{4d01f225-6cc5-11da-be43-001422106990},0,-1,1 +884,nsILivemarkService,{62a5fe00-d85c-4a63-aef7-176d8f1b189d},0,-1,1 +885,nsIDOMSVGDocument,{12d3b664-1dd2-11b2-a7cf-ceee7e90f396},0,-1,1 +886,nsIDOMHTMLLIElement,{a6cf909e-15b3-11d2-932e-00805f8add32},0,-1,1 +887,nsIDOMParserJS,{ba6bcd6c-63d8-49b3-bc8a-1e5e895645bc},0,-1,1 +888,nsIDOMHTMLUListElement,{a6cf9099-15b3-11d2-932e-00805f8add32},0,-1,1 +889,nsIDOMXULContainerElement,{bc07c626-4294-43ae-9b0a-e726de0adcad},0,-1,1 +890,nsIClipboardOwner,{5a31c7a1-e122-11d2-9a57-000064657374},0,-1,1 +891,nsIDOMSimpleGestureEvent,{cb68e879-f710-415d-a871-9a550860df01},0,-1,1 +892,nsIScriptableInterfaces,{01c78c65-31da-456b-90bf-da39d09fdcbf},0,-1,1 +893,nsIURI,{07a22cc0-0ce5-11d3-9331-00104ba0fd40},0,-1,1 +894,nsIDOMSVGMatrix,{ec2da3ef-5a99-49ed-aaef-b5af916c14ac},0,-1,1 +895,nsIChannelClassifier,{1481c5b5-9f6e-4995-8fe3-2aad5c06440d},0,-1,1 +896,nsIDOMHTMLTableElement,{a6cf90b2-15b3-11d2-932e-00805f8add32},0,-1,1 +897,nsIDOMSVGEvent,{13aed1cc-a505-45d5-bbc2-0052c6bf200f},0,-1,1 +898,nsIContextMenuListener2,{7fb719b3-d804-4964-9596-77cf924ee314},0,-1,1 +899,nsIIOUtil,{e8152f7f-4209-4c63-ad23-c3d2aa0c5a49},0,-1,1 +900,nsISimpleStreamListener,{a9b84f6a-0824-4278-bae6-bfca0570a26e},0,-1,1 +901,nsIDOMWindowUtils,{6a60fde5-a00a-4732-bbea-2787c174c04f},0,-1,1 +902,nsIDOMXULPopupElement,{c32390a8-2bd8-4d1b-bf9f-1b1d0a944d19},0,-1,1 +903,nsIDOMNSMouseEvent,{1b8e528d-7dca-44ee-8ee6-c44594ebcef1},0,-1,1 +904,mozIStorageBindingParamsArray,{e676e1a3-1dc6-4802-ac03-291fa9de7f93},0,-1,1 +905,nsICacheService,{de114eb4-29fc-4959-b2f7-2d03eb9bc771},0,-1,1 +906,nsIFileView,{60b320d2-1dd2-11b2-bd73-dc3575f78ddd},0,-1,1 +907,nsIConsoleService,{883472a0-ea9b-11da-8ad9-0800200c9a66},0,-1,1 +908,nsIDocShellTreeOwner,{bc0eb30e-656e-491e-a7ae-7f460b660c8d},0,-1,1 +909,nsIDOMHTMLOListElement,{a6cf909a-15b3-11d2-932e-00805f8add32},0,-1,1 +910,nsIContextMenuListener,{3478b6b0-3875-11d4-94ef-0020183bf181},0,-1,1 +911,nsIExceptionManager,{efc9d00b-231c-4feb-852c-ac017266a415},0,-1,1 +912,nsIDOMSVGViewSpec,{ede34b03-57b6-45bf-a259-3550b5697286},0,-1,1 +913,nsINativeTreeView,{38e0b44d-fa08-458c-83fb-3e10b12aeb45},0,-1,0 +914,nsIPluginTagInfo,{6d827df5-b5cd-416c-85cb-3cdd05c7aed1},0,-1,0 +915,nsIInlineSpellChecker,{07be036a-2355-4a92-b150-5c9b7e9fdf2f},0,-1,1 +916,nsIDOMSVGFEOffsetElement,{c080f191-b22c-4fc0-85d5-a79dc3fa7ec8},0,-1,1 +917,nsIJSRuntimeService,{e7d09265-4c23-4028-b1b0-c99e02aa78f8},0,-1,0 +918,nsIHelperAppLauncherDialog,{f3704fdc-8ae6-4eba-a3c3-f02958ac0649},0,-1,1 +919,xpcIJSModuleLoader,{89da3673-e699-4f26-9ed7-11a528011434},0,-1,1 +920,nsIPluginTag,{13a1b39e-72e5-442d-aa73-5905ffaf837b},0,-1,1 +921,nsIRDFInt,{e13a24e3-c77a-11d2-80be-006097b76b8e},0,-1,1 +922,nsIRDFInferDataSource,{2b04860f-4017-40f6-8a57-784a1e35077a},0,-1,1 +923,nsIDOMSVGCircleElement,{0f89f2a4-b168-4602-90f5-1874418c0a6a},0,-1,1 +924,nsIJSContextStackIterator,{c7e6b7aa-fc12-4ca7-b140-98c38b698961},0,-1,0 +925,nsIProperty,{6dcf9030-a49f-11d5-910d-0010a4e73d9a},0,-1,1 +926,nsIDOMStyleSheetList,{a6cf9081-15b3-11d2-932e-00805f8add32},0,-1,1 +927,nsIDNSRecord,{31c9c52e-1100-457d-abac-d2729e43f506},0,-1,1 +928,nsIDOMSVGPathSegCurvetoCubicSmoothRel,{dd5b4b00-edaa-493a-b477-bbc2576b4a98},0,-1,1 +929,nsIDOMCSSCharsetRule,{19fe78cc-65ff-4b1d-a5d7-9ea89692cec6},0,-1,1 +930,nsILoginManagerStorage,{e66c97cd-3bcf-4eee-9937-38f650372d77},0,-1,1 +931,nsIPrefetchService,{cba513eb-c457-4b93-832c-1a979e66edd1},0,-1,1 +932,nsIDOMNSDocumentStyle,{26311d10-7e24-4c7b-bb3d-17aad86f4d88},0,-1,1 +933,nsIObjectOutputStream,{92c898ac-5fde-4b99-87b3-5d486422094b},0,-1,1 +934,nsIDOMSVGAnimatedRect,{ca45959e-f1da-46f6-af19-1ecdc322285a},0,-1,1 +935,nsIDOMHTMLLabelElement,{a6cf9096-15b3-11d2-932e-00805f8add32},0,-1,1 +936,nsIResumableChannel,{4ad136fa-83af-4a22-a76e-503642c0f4a8},0,-1,1 +937,nsIScriptLoaderObserver,{7b787204-76fb-4764-96f1-fb7a666db4f4},0,-1,1 +938,nsIHttpChannelInternal,{0eb66361-faaa-4e52-8c7e-6c25f11f8e3c},0,-1,1 +939,nsICollationFactory,{04971e14-d6b3-4ada-8cbb-c3a13842b349},0,-1,1 +940,nsIXPointerResult,{d3992637-f474-4b65-83ed-323fe69c60d2},0,-1,1 +941,nsITXTToHTMLConv,{933355f6-1dd2-11b2-a9b0-d335b9e35983},0,-1,1 +942,mozIStorageError,{1f350f96-7023-434a-8864-40a1c493aac1},0,-1,1 +943,nsIRequestObserverProxy,{7df8845f-938a-4437-9ea4-b11b850048f1},0,-1,1 +944,nsIWorkerNavigator,{74fb665a-e477-4ce2-b3c6-c58b1b28b6c3},0,-1,1 +945,nsISAXXMLReader,{5556997e-d816-4218-8b54-803d4261206e},0,-1,1 +946,nsIDOMLSResourceResolver,{9e61c7c8-8698-4477-9971-0923513919bd},0,-1,1 +947,nsIWritablePropertyBag,{96fc4671-eeb4-4823-9421-e50fb70ad353},0,-1,1 +948,nsIDownloadManager,{bacca1ac-1b01-4a6f-9e91-c2ead1f7d2c0},0,-1,1 +949,nsIDOM3Document,{2e0e9ea1-72ab-4d9e-bdeb-ca64e1abeba4},0,-1,1 +950,nsIDOMPageTransitionEvent,{b712418b-376f-4f75-b156-5d9ad99fe51f},0,-1,1 +951,nsIArray,{114744d9-c369-456e-b55a-52fe52880d2d},0,-1,1 +952,nsIDOMDocumentView,{1acdb2ba-1dd2-11b2-95bc-9542495d2569},0,-1,1 +953,nsIOfflineCacheUpdate,{877261bb-b952-4d27-847e-859bdd47c0ec},0,-1,1 +954,nsIAccessibleRetrieval,{244e4c67-a1d3-44f2-9cab-cdaa31b68046},0,-1,1 +955,nsIDOMMimeTypeArray,{f6134683-f28b-11d2-8360-c90899049c3c},0,-1,1 +956,nsISidebar,{67cf6231-c303-4f7e-b9b1-a0e87772ecfd},0,-1,1 +957,nsIMutableArray,{af059da0-c85b-40ec-af07-ae4bfdc192cc},0,-1,1 +958,nsIDOMCSS2Properties,{529b987a-cb21-4d58-99d7-9586e7662801},0,-1,1 +959,nsIHashable,{17e595fa-b57a-4933-bd0f-b1812e8ab188},0,-1,1 +960,nsIDOMGeoPositionAddress_MOZILLA_1_9_2_BRANCH,{98808deb-c8e4-422c-ba97-08bf2031464c},0,-1,1 +961,nsIDOMNSUIEvent,{72c9f79c-98cd-4224-a467-86b59c0a38f7},0,-1,1 +962,fuelIBookmark,{808585b6-7568-4b26-8c62-545221bf2b8c},0,-1,1 +963,nsIDOMSVGMarkerElement,{6a3b7b40-e65a-4e9c-9ee7-ca03ed0a18c7},0,-1,1 +964,nsIDOMDOMConstructor,{0ccbcf19-d1b4-489e-984c-cd8c43672bb9},0,-1,1 +965,nsIDOMUIEvent,{a6cf90c3-15b3-11d2-932e-00805f8add32},0,-1,1 +966,nsIRDFResource,{fb9686a7-719a-49dc-9107-10dea5739341},0,-1,1 +967,nsIDOMFileException,{b52356e1-45c5-4d61-b61a-fb9bd91690e1},0,-1,1 +968,nsIXULTemplateResult,{ebea0230-36fa-41b7-8e31-760806057965},0,-1,1 +969,nsIDOMSVGLength,{2596325c-aed0-487e-96a1-0a6d589b9c6b},0,-1,1 +970,imgIContainerObserver,{e214c295-4b8e-4aa9-9907-45289e57295b},0,-1,1 +971,nsIDOMCSSRule,{a6cf90c1-15b3-11d2-932e-00805f8add32},0,-1,1 +972,nsIDOMSVGPreserveAspectRatio,{7ae42f27-4799-4e7c-86c6-e1dae6ad5157},0,-1,1 +973,nsIEditorDocShell,{3bdb8f01-f141-11d4-a73c-fba4aba8a3fc},0,-1,1 +974,nsIDocumentCharsetInfo,{2d40b291-01e1-11d4-9d0e-0050040007b2},0,-1,1 +975,nsIConsoleListener,{eaaf61d6-1dd1-11b2-bc6e-8fc96480f20d},0,-1,1 +976,nsIProgrammingLanguage,{ea604e90-40ba-11d5-90bb-0010a4e73d9a},0,-1,1 +977,nsIDOMNSHTMLImageElement,{a6cf90c7-15b3-11d2-932e-00805f8add32},0,-1,1 +978,nsIUnicharStreamLoader,{9037f476-7c08-4729-b690-3e425269802b},0,-1,1 +979,nsIFrameLoaderOwner,{641c2d90-4ada-4367-bdb1-80831614161d},0,-1,1 +980,nsIDOMHTMLAreaElement,{a6cf90b0-15b3-11d2-932e-00805f8add32},0,-1,1 +981,nsIKeyObject,{4b31f4ed-9424-4710-b946-79b7e33cf3a8},0,-1,1 +982,nsIMIMEService,{5b3675a1-02db-4f8f-a560-b34736635f47},0,-1,1 +983,nsIDOMWindow2,{73c5fa35-3add-4c87-a303-a850ccf4d65a},0,-1,1 +984,nsIDOMWindow,{a6cf906b-15b3-11d2-932e-00805f8add32},0,-1,1 +985,nsPISocketTransportService,{83123036-81c0-47cb-8d9c-bd85d29a1b3f},0,-1,1 +986,nsIDOMGeoPositionOptions,{453b72de-ea90-4f09-ae16-c2e7ee0dddc4},0,-1,1 +987,nsIURLFormatter,{4ab31d30-372d-11db-a98b-0800200c9a66},0,-1,1 +988,nsICacheEntryInfo,{fab51c92-95c3-4468-b317-7de4d7588254},0,-1,1 +989,imgIContainer,{1bcf7a25-1356-47a8-bf80-e284989ea38f},0,-1,1 +990,nsIDOMSVGPolylineElement,{7b6e15cf-9793-41ee-adcc-cc1c206c80e6},0,-1,1 +991,nsPIWindowWatcher,{8624594a-28d7-4bc3-8d12-b1c2b9eefd90},0,-1,0 +992,nsIFeedResult,{7a180b78-0f46-4569-8c22-f3d720ea1c57},0,-1,1 +993,nsIDOMPaintRequest,{4802360b-f1c0-4d84-bb9e-9d2ccb9de461},0,-1,1 +994,nsIDOMSVGSVGElement,{83b04425-9509-49f5-af75-1ae1f8f3e871},0,-1,1 +995,nsIFormSubmitObserver,{0787d64a-44bf-4273-8438-61ff13ebec0c},0,-1,1 +996,nsIDOMUserDataHandler,{91afebdd-a201-4db0-b728-9d59580f0cfd},0,-1,1 +997,nsIDOMXULTreeElement,{1f8111b2-d44d-4d11-845a-a70ae06b7d04},0,-1,1 +998,nsIDOMSVGTextContentElement,{87ad94bc-07c9-412b-b2d8-de245a2e84a5},0,-1,1 +999,nsIDOM3Node,{29fb2a18-1dd2-11b2-8dd9-a6fd5d5ad12f},0,-1,1 +1000,nsIDirectoryServiceProvider2,{2f977d4b-5485-11d4-87e2-0010a4e75ef2},0,-1,1 +1001,nsIWebPageDescriptor,{6f30b676-3710-4c2c-80b1-0395fb26516e},0,-1,1 +1002,nsINetworkLinkService,{61618a52-ea91-4277-a4ab-ebe10d7b9a64},0,-1,1 +1003,nsIDOMHTMLParamElement,{a6cf90ad-15b3-11d2-932e-00805f8add32},0,-1,1 +1004,jsdIValue,{9cab158f-dc78-41dd-9d11-79e05cb3f2bd},0,-1,1 +1005,nsIDOMSVGFESpotLightElement,{5515dd05-3d9d-4d6c-8460-a04aaf5afe15},0,-1,1 +1006,jsdIScript,{18e09893-f461-4b4b-94d3-776fb0069c6f},0,-1,1 +1007,nsIFaviconService,{66f6b992-e2d3-43da-ba2a-d966e34a7654},0,-1,1 +1008,nsIClassInfo,{986c11d0-f340-11d4-9075-0010a4e73d9a},0,-1,1 +1009,nsIDOMFileError,{4bdafb64-15e2-49c1-a090-4315a7884a56},0,-1,1 +1010,nsISOCKSSocketInfo,{8f755c44-1dd2-11b2-a613-91117453fa95},0,-1,1 +1011,nsISupportsPriority,{aa578b44-abd5-4c19-8b14-36d4de6fdc36},0,-1,1 +1012,nsIKeyObjectFactory,{264eb54d-e20d-49a0-890c-1a5986ea81c4},0,-1,1 +1013,nsIWifiListener,{bcd4bede-f4a5-4a62-9071-d7a60174e376},0,-1,1 +1014,nsIInputStream,{fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a},0,-1,1 +1015,nsISecurityCheckedComponent,{0dad9e8c-a12d-4dcb-9a6f-7d09839356e1},0,-1,1 +1016,nsIDOMSVGAnimatedPoints,{ebf334b3-86ef-4bf3-8a92-d775c72defa4},0,-1,1 +1017,nsIDOMHTMLFormElement,{a6cf908f-15b3-11d2-932e-00805f8add32},0,-1,1 +1018,nsIDOMCanvasRenderingContext2D,{3e7d5d06-8846-4cff-8739-44756cbf494f},0,-1,1 +1019,nsIScriptableInterfacesByID,{c99cffac-5aed-4267-ad2f-f4a4c9d4a081},0,-1,1 +1020,nsIConverterOutputStream,{4b71113a-cb0d-479f-8ed5-01daeba2e8d4},0,-1,1 +1021,nsIDOMViewCSS,{0b9341f3-95d4-4fa4-adcd-e119e0db2889},0,-1,1 +1022,nsIEnvironment,{101d5941-d820-4e85-a266-9a3469940807},0,-1,1 +1023,nsITreeColumns,{f8a8d6b4-6788-438d-9009-7142798767ab},0,-1,1 +1024,nsIDOMHTMLHtmlElement,{a6cf9086-15b3-11d2-932e-00805f8add32},0,-1,1 +1025,nsIHttpProtocolHandler,{415d4087-79d3-40fe-b194-0ada8471f895},0,-1,1 +1026,nsIDOMSVGUnitTypes,{154b572f-3d0b-49c0-8b5d-8864d05bd3d1},0,-1,1 +1027,nsIImageLoadingContent,{e036857e-3417-4812-a5f2-89668a616781},0,-1,1 +1028,nsIRDFXMLSerializer,{8ae1fbf8-1dd2-11b2-bd21-d728069cca92},0,-1,1 +1029,nsICookie,{e9fcb9a4-d376-458f-b720-e65e7df593bc},0,-1,1 +1030,nsICMSEncoder,{a15789aa-8903-462b-81e9-4aa2cff4d5cb},0,-1,0 +1031,nsISelectElement,{35bd8ed5-5f34-4126-8c4f-38ba01681836},0,-1,0 +1032,nsIAddonRepository,{c4d2ac29-6edc-43cd-8dc8-e4cf213aa1be},0,-1,1 +1033,extIEventListener,{2dfe3a50-ab2f-11db-abbd-0800200c9a66},0,-1,1 +1034,nsIRDFContainer,{d4214e90-fb94-11d2-bdd8-00104bde6048},0,-1,1 +1035,nsIXPIInstallInfo,{5a4a775c-e452-4cf2-8ff8-d327ae24aec6},0,-1,1 +1036,nsINavBookmarksService,{3b6ff5c5-0ab4-4aab-b1be-d569763a6ce0},0,-1,1 +1037,nsIThreadManager,{056216f5-8803-46b4-9199-d95bc1f0446f},0,-1,1 +1038,nsIDOMLinkStyle,{24d89a65-f598-481e-a297-23cc02599bbd},0,-1,1 +1039,nsIDOMSVGPoint,{45f18f8f-1315-4447-a7d5-8aeca77bdcaf},0,-1,1 +1040,nsIXMLHttpRequest,{ad78bf21-2227-447e-8ed5-824a017c265f},0,-1,1 +1041,nsISupportsCString,{d65ff270-4a1c-11d3-9890-006008962422},0,-1,1 +1042,nsIDebug,{3bf0c3d7-3bd9-4cf2-a971-33572c503e1e},0,-1,1 +1043,IDispatch,{00020400-0000-0000-c000-000000000046},0,-1,1 +1044,nsIEntropyCollector,{6f883680-ab9d-11d4-9978-00b0d02354a0},0,-1,0 +1045,nsIDOMEvent,{a66b7b80-ff46-bd97-0080-5f8ae38add32},0,-1,1 +1046,nsIFeedResultListener,{4d2ebe88-36eb-4e20-bcd1-997b3c1f24ce},0,-1,1 +1047,nsIDOMTreeWalker,{400af3ca-1dd2-11b2-a50a-887ecca2e63a},0,-1,1 +1048,inICSSValueSearch,{e0d39e48-1dd1-11b2-81bd-9a0c117f0736},0,-1,1 +1049,nsIProcess,{3c09efde-5f49-42b8-8520-57be02a5f84e},0,-1,1 +1050,nsIWindowCreator,{30465632-a777-44cc-90f9-8145475ef999},0,-1,1 +1051,nsIScriptSecurityManager_1_9_2,{8229dd23-47c5-4601-a80b-0166d595a21e},0,-1,1 +1052,nsIDOMDocumentXBL,{1a38762b-4da5-4f61-80fb-9317e198cb92},0,-1,1 +1053,nsIObserverService,{d07f5192-e3d1-11d2-8acd-00105a1b8860},0,-1,1 +1054,nsIApplicationCacheService,{611161c8-37d0-450f-a4fe-457c47bbaf64},0,-1,1 +1055,nsIDBusHandlerApp,{1ffc274b-4cbf-4bb5-a635-05ad2cbb6534},0,-1,1 +1056,nsIDOMHTMLFrameSetElement,{a6cf90b8-15b3-11d2-932e-00805f8add32},0,-1,1 +1057,nsICertOverrideService,{31738d2a-77d3-4359-84c9-4be2f38fb8c5},0,-1,1 +1058,nsIPipe,{f4211abc-61b3-11d4-9877-00c04fa0cf4a},0,-1,1 +1059,nsINavHistoryBatchCallback,{5143f2bb-be0a-4faf-9acb-b0ed3f82952c},0,-1,1 +1060,nsIFactory,{00000001-0000-0000-c000-000000000046},0,-1,1 +1061,nsILoadContext,{314d8a54-1caf-4721-94d7-f6c82d9b82ed},0,-1,1 +1062,nsIProtectedAuthThread,{4bb27cb7-8984-4cee-8ce7-9b014c3d091b},0,-1,1 +1063,nsIFIXptrEvaluator,{50d28211-8fb8-4323-b93d-08a6e80e559e},0,-1,0 +1064,nsISupportsPRTime,{e2563630-4a1c-11d3-9890-006008962422},0,-1,1 +1065,nsIDOMSVGStopElement,{93169940-7663-4eab-af23-94a8a08c2654},0,-1,1 +1066,inISearchProcess,{d5fa765b-2448-4686-b7c1-5ff13acb0fc9},0,-1,1 +1067,nsIDOMSVGRect,{5b912111-c10e-498f-a44c-c713c1843007},0,-1,1 +1068,nsISecurityPref,{94afd973-8045-4c6c-89e6-75bdced4209e},0,-1,0 +1069,nsIFeedTextConstruct,{fc97a2a9-d649-4494-931e-db81a156c873},0,-1,1 +1070,nsIIncrementalDownload,{6687823f-56c4-461d-93a1-7f6cb7dfbfba},0,-1,1 +1071,nsIDocShellHistory,{89caa9f0-8b1c-47fb-b0d3-f0aef0bff749},0,-1,1 +1072,nsICacheSession,{ae9e84b5-3e2d-457e-8fcd-5bbd2a8b832e},0,-1,1 +1073,txIFunctionEvaluationContext,{0ecbb00c-6a78-11d9-9791-000a95dc234c},0,-1,1 +1074,nsIDOMHTMLEmbedElement,{123f90ab-15b3-11d2-456e-00805f8add32},0,-1,1 +1075,nsIDOMHTMLAnchorElement,{a6cf90aa-15b3-11d2-932e-00805f8add32},0,-1,1 +1076,nsICharsetConverterManager,{f5323a76-c8f7-4c65-8d0c-1250e969c7d5},0,-1,1 +1077,nsIApplicationCacheNamespace,{96e4c264-2065-4ce9-93bb-43734c62c4eb},0,-1,1 +1078,nsIProfileMigrator,{24ce8b9d-b7ff-4279-aef4-26e158f03e34},0,-1,1 +1079,nsIRDFPropagatableDataSource,{5a9b4770-9fcb-4307-a12e-4b6708e78b97},0,-1,1 +1080,mozISpellI18NUtil,{b075d5dc-1df1-441a-bebf-680d8caaa19c},0,-1,1 +1081,nsIGlobalHistory3,{24306852-c60e-49c3-a455-90f6747118ba},0,-1,1 +1082,nsIScriptEventHandler,{375f787f-8d3a-4344-b540-293d5645c22c},0,-1,0 +1083,nsIDOMChromeWindow,{09b86cbd-9784-4fe4-9be6-70b9bbca3a9c},0,-1,1 +1084,nsISupports,{00000000-0000-0000-c000-000000000046},0,-1,1 +1085,nsIFileProtocolHandler,{1fb25bd5-4354-4dcd-8d97-621b7b3ed2e4},0,-1,1 +1086,nsILoginManagerIEMigrationHelper,{8a59ea3d-b8d0-48af-a3e2-63e27a02cde7},0,-1,1 +1087,nsIMicrosummarySet,{7111e88d-fecd-4b17-b7a9-1fa74e23153f},0,-1,1 +1088,nsIFeedEntry,{31bfd5b4-8ff5-4bfd-a8cb-b3dfbd4f0a5b},0,-1,1 +1089,nsIDragSession_1_9_2,{fde41f6a-c710-46f8-a0a8-1ff76ca4ff57},0,-1,1 +1090,nsIURIClassifierCallback,{8face46e-0c96-470f-af40-0037dcd797bd},0,-1,1 +1091,nsIXPCComponents_Constructor,{88655640-e028-11d3-8f5d-0010a4e73d9a},0,-1,1 +1092,nsIXPCException,{cac29630-7bf2-4e22-811b-46855a7d5af0},0,-1,1 +1093,nsIRDFXMLSinkObserver,{eb1a5d30-ab33-11d2-8ec6-00805f29f370},0,-1,1 +1094,nsIDOMLSSerializer,{96ea4792-d362-4c28-a8c2-0337790d648a},0,-1,1 +1095,nsIDownloadProgressListener,{7acb07ea-cac2-4c15-a3ad-23aaa789ed51},0,-1,1 +1096,nsIOutputIterator,{7330650e-1dd2-11b2-a0c2-9ff86ee97bed},0,-1,1 +1097,nsIPluginStreamInfo,{3a5fa31d-1ac1-4ea7-b7a6-dc9db0000b79},0,-1,0 +1098,nsIDOMHTMLQuoteElement,{a6cf90a3-15b3-11d2-932e-00805f8add32},0,-1,1 +1099,nsIPlacesTransactionsService,{32eee5da-2bc7-4d18-8a54-a8ff0dec4d2a},0,-1,1 +1100,nsIX509Cert2,{5b62c61c-f898-4dab-8ace-51109bb459b4},0,-1,1 +1101,nsIFeedResultService,{950a829e-c20e-4dc3-b447-f8b753ae54da},0,-1,1 +1102,nsIMarkupDocumentViewer,{40b2282a-a882-4483-a634-dec468d88377},0,-1,1 +1103,txINodeSet,{15d424c0-6b47-11d9-9791-000a95dc234c},0,-1,1 +1104,nsIDOMSVGFEMergeNodeElement,{540c3447-4b07-4bd3-84df-30f66b68df14},0,-1,1 +1105,nsIAccelerometer,{4b04e228-0b33-43fc-971f-af60cedb1c21},0,-1,1 +1106,nsIDOMSVGPathSegMovetoAbs,{30cf7749-bf1f-4f9c-9558-8ee24da3a22c},0,-1,1 +1107,nsIScriptableInputStream,{a2a32f90-9b90-11d3-a189-0050041caf44},0,-1,1 +1108,nsIDOMLSInput,{165e7f61-5048-4c2c-b4bf-6b44bb617ee4},0,-1,1 +1109,nsIContentURIGrouper,{4bb38cb4-c3cb-4d17-9799-1b3132b39723},0,-1,1 +1110,nsICharsetConverterManager_1_9_BRANCH,{36982132-707c-4d77-b27f-958e76e022de},0,-1,1 +1111,nsIScriptableUnicodeConverter,{1ea19c6c-c59f-4fd7-9fc7-151e946baca0},0,-1,1 +1112,nsIEditorIMESupport,{57032dcb-e8c7-4eb6-8ec6-a0f8e300809d},0,-1,1 +1113,nsISelection2,{5d21d5fe-3691-4716-a334-4691eea54d29},0,-1,1 +1114,nsIDOMHTMLHeadingElement,{a6cf90a2-15b3-11d2-932e-00805f8add32},0,-1,1 +1115,nsIWebNavigationInfo,{62a93afb-93a1-465c-84c8-0432264229de},0,-1,1 +1116,nsIAccessibleDocument,{b7ae45bd-21e9-4ed5-a67e-86448b25d56b},0,-1,1 +1117,nsIStreamListener,{1a637020-1482-11d3-9333-00104ba0fd40},0,-1,1 +1118,nsIOutputStreamCallback,{40dbcdff-9053-42c5-a57c-3ec910d0f148},0,-1,1 +1119,jsdIScriptEnumerator,{5ba76b99-acb1-4ed8-a4e4-a716a7d9097e},0,-1,1 +1120,nsIWebProgress,{570f39d0-efd0-11d3-b093-00a024ffc08c},0,-1,1 +1121,nsIBoxObject,{ce572460-b0f2-4650-a9e7-c53a99d3b6ad},0,-1,1 +1122,nsIXULChromeRegistry,{2860e205-490e-4b06-90b6-87160d35a5a7},0,-1,1 +1123,nsIScreenManager,{b92319e6-9a84-4ca7-a2cc-eec22ea9854e},0,-1,1 +1124,nsIUpdateTimerManager,{0765c92c-6145-4253-9db4-594d8023087e},0,-1,1 +1125,nsIJSCID,{26b2a374-6eaf-46d4-acaf-1c6be152d36b},0,-1,1 +1126,nsIDOMNSElement,{c9da11bc-32d4-425e-a91f-7e0939c39251},0,-1,1 +1127,nsIHttpChannel,{9277fe09-f0cc-4cd9-bbce-581dd94b0260},0,-1,1 +1128,txIEXSLTRegExFunctions,{c180e993-aced-4839-95a0-ecd5ff138be9},0,-1,1 +1129,nsIPrinterEnumerator,{5e738fff-404c-4c94-9189-e8f2cce93e94},0,-1,1 +1130,mozISpellI18NManager,{aeb8936f-219c-4d3c-8385-d9382daa551a},0,-1,1 +1131,nsIPluginInstance,{67d606f4-1d6d-4fe2-a2d6-10bda65788e1},0,-1,0 +1132,nsIIdleService,{cc52f19a-63ae-4a1c-9cc3-e79eace0b471},0,-1,1 +1133,nsIDownload,{c891111e-92a6-47b8-bc46-874ebb61ac9d},0,-1,1 +1134,nsIObjectLoadingContent,{90ab443e-3e99-405e-88c9-9c42adaa3217},0,-1,1 +1135,nsIAuthPromptProvider,{bd9dc0fa-68ce-47d0-8859-6418c2ae8576},0,-1,1 +1136,nsISelection,{b2c7ed59-8634-4352-9e37-5484c8b6e4e1},0,-1,1 +1137,nsIAccessibleRole,{6793ca5c-c7cb-41db-9fb9-c16c0525f962},0,-1,1 +1138,mozIStorageBindingParams,{a8d4827c-641c-45e3-a9ea-493570b4106b},0,-1,1 +1139,nsIXPointerSchemeProcessor,{093d3559-b56b-44d0-8764-c25815715080},0,-1,0 +1140,nsIDOMSVGLengthList,{a8760fcd-3de5-446a-a009-5cf877e7a4df},0,-1,1 +1141,nsIRDFDelegateFactory,{a1b89470-a124-11d3-be59-0020a6361667},0,-1,1 +1142,nsIWebContentConverterService,{de7cc06e-e778-45cb-b7db-7a114e1e75b1},0,-1,1 +1143,nsIUrlClassifierHashCompleterCallback,{bbd6c954-7cb4-4447-bc55-8cefd1ceed89},0,-1,1 +1144,nsIX509CertDB2,{e0df4784-6560-45bf-b1b7-86076a0e8381},0,-1,1 +1145,nsIDOMTextMetrics,{2d01715c-ec7d-424a-ab85-e0fd70c8665c},0,-1,1 +1146,nsILoadGroup,{3de0a31c-feaf-400f-9f1e-4ef71f8b20cc},0,-1,1 +1147,nsIExtensionManager,{494e8302-8689-4a8a-a08d-0da17c649c7d},0,-1,1 +1148,nsICharsetResolver,{d143a084-b626-4614-845f-41f3ca43a674},0,-1,1 +1149,nsIEditActionListener,{b22907b1-ee93-11d2-8d50-000064657374},0,-1,1 +1150,nsIProperties,{78650582-4e93-4b60-8e85-26ebd3eb14ca},0,-1,1 +1151,nsIUserCertPicker,{06d018e0-d41b-4629-a4fc-daaa6029888e},0,-1,1 +1152,nsIAccessibilityService,{6a58f7e8-587c-40dd-b684-dc3e54f1342a},0,-1,0 +1153,nsIDOMSVGAElement,{35d3365a-3e6f-4cdf-983d-fdaed1564478},0,-1,1 +1154,nsIDOMSVGTransform,{29cc2e14-6d18-4710-bda9-a88d9d3bc8dc},0,-1,1 +1155,nsICommandLineRunner,{c1f4cfbf-a41f-4628-aa6c-9fb914478af8},0,-1,0 +1156,nsIPromptService2,{cf86d196-dbee-4482-9dfa-3477aa128319},0,-1,1 +1157,nsIDOMDocument,{a6cf9075-15b3-11d2-932e-00805f8add32},0,-1,1 +1158,nsIPluginStreamListener,{df055770-5448-11d2-8164-006008119d7a},0,-1,0 +1159,mozIStorageAggregateFunction,{763217b7-3123-11da-918d-000347412e16},0,-1,1 +1160,nsPIExternalAppLauncher,{d0b5d7d3-9565-403d-9fb5-e5089c4567c6},0,-1,1 +1161,nsIDOMProcessingInstruction,{a6cf907f-15b3-11d2-932e-00805f8add32},0,-1,1 +1162,nsITreeBoxObject,{64ba5199-c4f4-4498-bbdc-f8e4c369086c},0,-1,1 +1163,nsIDOMNSRange,{59188642-23b4-41d6-bde1-302c3906d1f0},0,-1,1 +1164,nsIDOMSVGAngle,{58b6190e-37b3-412a-ba02-1d5ad6c6ea7c},0,-1,1 +1165,nsIDOMXPathEvaluator,{75506f8a-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +1166,nsIXPointerEvaluator,{addd0fe5-8555-45b7-b763-97d5898ce268},0,-1,0 +1167,nsISecretDecoderRing,{0ec80360-075c-11d4-9fd4-00c04f1b83d8},0,-1,1 +1168,nsIAutoCompleteMdbResult2,{148c9dc5-0fbb-408b-80fe-544f6a85b433},0,-1,0 +1169,nsIPrintOptions,{92597c2b-109b-40bb-8f93-9b9acfa31de8},0,-1,1 +1170,nsIHttpActivityObserver,{412880c8-6c36-48d8-bf8f-84f91f892503},0,-1,1 +1171,nsITraceableChannel,{68167b0b-ef34-4d79-a09a-8045f7c5140e},0,-1,1 +1172,nsIBrowserBoxObject,{db436f2f-c656-4754-b0fa-99bc353bd63f},0,-1,1 +1173,nsIAddonInstallListener,{2333b04c-f371-4dea-a2f1-d8fdb0c82866},0,-1,1 +1174,nsIDOMGeoPositionCoords,{b31702d0-6dac-4fa0-b93b-f043e71c8f9a},0,-1,1 +1175,nsIDOMElementCSSInlineStyle,{99715845-95fc-4a56-aa53-214b65c26e22},0,-1,1 +1176,nsIDOMSVGNumber,{98575762-a936-4ecf-a226-b74c3a2981b4},0,-1,1 +1177,nsICommandLine,{bc3173bd-aa46-46a0-9d25-d9867a9659b6},0,-1,1 +1178,nsIDOMModalContentWindow,{51aebd45-b979-4ec6-9d11-3a3fd3d5d59e},0,-1,1 +1179,nsIAccessibleTable,{035c0c0e-41e3-4985-8ad9-d9f14cdc667a},0,-1,1 +1180,nsICryptoHash,{1e5b7c43-4688-45ce-92e1-77ed931e3bbe},0,-1,1 +1181,nsIAnnotationService,{ba249b58-346f-42a9-a393-203ae34ec6c4},0,-1,1 +1182,nsIDOMHTMLStyleElement,{a6cf908d-15b3-11d2-932e-00805f8add32},0,-1,1 +1183,nsIDOMNSHTMLFormElement,{a6cf90c6-15b3-11d2-932e-00805f8add32},0,-1,1 +1184,nsIAuthPromptWrapper,{6228d644-17fe-11d4-8cee-0060b0fc14a3},0,-1,1 +1185,nsICollection,{83b6019c-cbc4-11d2-8cca-0060b0fc14a3},0,-1,1 +1186,nsIStringBundleOverride,{965eb278-5678-456b-82a7-20a0c86a803c},0,-1,1 +1187,nsIAuthPromptCallback,{bdc387d7-2d29-4cac-92f1-dd75d786631d},0,-1,1 +1188,nsIJSXMLHttpRequest,{423fdd3d-41c9-4149-8fe5-b14a1d3912a0},0,-1,1 +1189,nsIDOMSVGFEFuncGElement,{28555e78-c6c2-4a98-af53-bfc2c6944295},0,-1,1 +1190,nsIProgressEventSink,{d974c99e-4148-4df9-8d98-de834a2f6462},0,-1,1 +1191,nsIDOMSVGFETurbulenceElement,{77bc4d70-0d49-4c81-b7a7-7432f0fe3e04},0,-1,1 +1192,nsIDOMXULControlElement,{007b8358-1dd2-11b2-8924-d209efc3f124},0,-1,1 +1193,nsICacheDeviceInfo,{31d1c294-1dd2-11b2-be3a-c79230dca297},0,-1,1 +1194,imgITools,{c395d8f1-c616-4a1b-adfd-747b4b1b2cbe},0,-1,1 +1195,nsIContentViewerFile,{6317f32c-9bc7-11d3-bccc-0060b0fc76bd},0,-1,1 +1196,nsIDOMSVGPatternElement,{bc435244-b748-4e14-9e4c-219d5d3cb218},0,-1,1 +1197,nsIAccessibleCoordinateType,{c9fbdf10-619e-436f-bf4b-8566686f1577},0,-1,1 +1198,nsIConverterInputStream,{fc66ffb6-5404-4908-a4a3-27f92fa0579d},0,-1,1 +1199,nsIScreen,{f728830e-1dd1-11b2-9598-fb9f414f2465},0,-1,1 +1200,nsIDOMCSSPrimitiveValue,{e249031f-8df9-4e7a-b644-18946dce0019},0,-1,1 +1201,nsIDOMXULTextBoxElement,{71135b6c-294e-4634-a8e4-a72398f1e72a},0,-1,1 +1202,nsIDirIndexParser,{38e3066c-1dd2-11b2-9b59-8be515c1ee3f},0,-1,1 +1203,nsIDOMRGBColor,{6aff3102-320d-4986-9790-12316bb87cf9},0,-1,1 +1204,nsIDOMHTMLTableCaptionElement,{a6cf90b3-15b3-11d2-932e-00805f8add32},0,-1,1 +1205,nsIIFrameBoxObject,{30114c44-d398-44a5-9e01-b48b711291cd},0,-1,1 +1206,nsIPopupWindowManager,{3210a6aa-b464-4f57-9335-b22815567cf1},0,-1,1 +1207,extIEventItem,{05281820-ab62-11db-abbd-0800200c9a66},0,-1,1 +1208,nsIDOM3TypeInfo,{2a1088c7-499a-49a7-9d3b-1970d21532ab},0,-1,1 +1209,nsIDOMFileList,{3bfef9fa-8ad3-4e49-bd62-d6cd75b29298},0,-1,1 +1210,nsIWebContentHandlerInfo,{eb361098-5158-4b21-8f98-50b445f1f0b2},0,-1,1 +1211,nsIDOMNSHTMLFormControlList,{a6cf911a-15b3-11d2-932e-00805f8add32},0,-1,1 +1212,nsINavHistoryResultTreeViewer,{fa77e4e9-9fc8-45d2-9507-0fe4f0602505},0,-1,1 +1213,nsIXPCComponents_ClassesByID,{336a9590-4d19-11d3-9893-006008962422},0,-1,1 +1214,nsIDOM3Attr,{a2216ddc-1bcd-4ec2-a292-371e09a6c377},0,-1,1 +1215,nsIPrintingPromptService,{75d1553d-63bf-4b5d-a8f7-e4e4cac21ba4},0,-1,1 +1216,nsIDOMNSXPathExpression,{ce600ca8-e98a-4419-ad61-2f6d0cb0ecc8},0,-1,1 +1217,nsINavHistoryResultNode,{464ae28f-3a9c-4483-afb2-bb0fb0ddb893},0,-1,1 +1218,nsIDragSession,{15860d52-fe2c-4ddd-ac50-9c23e24916c4},0,-1,1 +1219,nsITransactionList,{97f863f3-f886-11d4-9d39-0060b0f8baff},0,-1,1 +1220,nsIDOMSVGPathSegCurvetoCubicRel,{0e661233-0c4f-4e0d-94d3-fbc460ad1f88},0,-1,1 +1221,nsIClipboardDragDropHookList,{876a2015-6b66-11d7-8f18-0003938a9d96},0,-1,1 +1222,nsIScrollable,{919e792a-6490-40b8-bba5-f9e9ad5640c8},0,-1,1 +1223,gfxIFormats,{96d086e6-1dd1-11b2-b6b2-b77b59390247},0,-1,1 +1224,nsISupportsPRBool,{ddc3b490-4a1c-11d3-9890-006008962422},0,-1,1 +1225,nsIDOMNodeFilter,{e4723748-1dd1-11b2-8ee6-866a532a6237},0,-1,1 +1226,nsISocketTransportService,{185b3a5d-8729-436d-9693-7bdccb9c2216},0,-1,1 +1227,nsIDOMNavigatorGeolocation,{9f218d6a-42ec-4b8a-aee9-e29ca96a4eae},0,-1,1 +1228,nsISelectionDisplay,{0ddf9e1c-1dd2-11b2-a183-908a08aa75ae},0,-1,1 +1229,nsIEventListenerService,{551cac0f-31ed-45e0-8d67-bc0d6e117b31},0,-1,1 +1230,nsIDOMNSEditableElement,{b33eb56c-3120-418c-892b-774b00c7dde8},0,-1,1 +1231,nsIClipboardDragDropHooks,{e03e6c5e-0d84-4c0b-8739-e6b8d51922de},0,-1,1 +1232,nsIGnomeVFSMimeApp,{66009894-9877-405b-9321-bf30420e34e6},0,-1,1 +1233,nsIPrintProgressParams,{ca89b55b-6faf-4051-9645-1c03ef5108f8},0,-1,1 +1234,nsIDOMCSSRuleList,{a6cf90c0-15b3-11d2-932e-00805f8add32},0,-1,1 +1235,nsIProtocolHandler,{15fd6940-8ea7-11d3-93ad-00104ba0fd40},0,-1,1 +1236,nsIHTMLObjectResizeListener,{27b00295-349c-429f-ad0c-87b859e77130},0,-1,1 +1237,nsIKeygenThread,{8712a243-5539-447c-9f47-8653f40c3a09},0,-1,1 +1238,nsIPersistentProperties,{1a180f60-93b2-11d2-9b8b-00805f8a16d9},0,-1,1 +1239,nsIXPCComponents_utils_Sandbox,{4f8ae0dc-d266-4a32-875b-6a9de71a8ce9},0,-1,1 +1240,nsIScriptableUnescapeHTML,{3ab244a9-f09d-44da-9e3f-ee4d67367f2d},0,-1,1 +1241,nsITransactionManager,{58e330c2-7b48-11d2-98b9-00805f297d89},0,-1,1 +1242,nsIURIRefObject,{2226927e-1dd2-11b2-b57f-faab47288563},0,-1,1 +1243,nsIDOMNSHTMLOptionElement,{e2dfc89c-7ae0-4651-8aee-7f5edc2aa626},0,-1,1 +1244,imgIDecoderObserver,{1dfc9189-6421-4281-83b2-d9c1c9ba4d1b},0,-1,1 +1245,nsICookieService,{2aaa897a-293c-4d2b-a657-8c9b7136996d},0,-1,1 +1246,nsIDOMEventTarget,{1c773b30-d1cf-11d2-bd95-00805f8ae3f4},0,-1,1 +1247,nsIWorkerScope,{5c55ea4b-e4ac-4ceb-bfeb-46bd5e521b8a},0,-1,1 +1248,nsIDOMSVGScriptElement,{bbe0d0ee-e9ed-4f84-a6e4-e58f66530caa},0,-1,1 +1249,nsIFTPEventSink,{455d4234-0330-43d2-bbfb-99afbecbfeb0},0,-1,1 +1250,nsIPermissionManager,{00708302-684c-42d6-a5a3-995d51b1d17c},0,-1,1 +1251,nsIXPCComponents,{155809f1-71f1-47c5-be97-d812ba560405},0,-1,1 +1252,nsIBlocklistService,{8439f9c0-da03-4260-8b21-dc635eed28fb},0,-1,1 +1253,nsIDOMEntity,{a6cf9079-15b3-11d2-932e-00805f8add32},0,-1,1 +1254,nsIWifiMonitor,{f289701e-d9af-4685-bc2f-e4226ff7c018},0,-1,1 +1255,nsIDOMHTMLBaseElement,{a6cf908b-15b3-11d2-932e-00805f8add32},0,-1,1 +1256,nsIFileInputStream,{e3d56a20-c7ec-11d3-8cda-0060b0fc14a3},0,-1,1 +1257,nsIDOMHTMLMenuElement,{a6cf909d-15b3-11d2-932e-00805f8add32},0,-1,1 +1258,nsIDOMHTMLDivElement,{a6cf90a0-15b3-11d2-932e-00805f8add32},0,-1,1 +1259,nsIPlacesImportExportService,{21c00314-fa63-11db-8314-0800200c9a66},0,-1,1 +1260,nsIRDFXMLSink,{eb1a5d31-ab33-11d2-8ec6-00805f29f370},0,-1,1 +1261,nsIDOMXULLabeledControlElement,{a457ea70-1dd1-11b2-9089-8fd894122084},0,-1,1 +1262,nsIZipWriter,{6d4ef074-206c-4649-9884-57bc355864d6},0,-1,1 +1263,nsIDOMSVGLineElement,{4ea07ef3-ed66-4b41-8119-4afc6d0ed5af},0,-1,1 +1264,nsIWifiAccessPoint,{e28e614f-8f86-44ff-bcf5-5f18225834a0},0,-1,1 +1265,nsISAXMutableAttributes,{8b1de83d-cebb-49fa-8245-c0fe319eb7b6},0,-1,1 +1266,nsIDOMXULSelectControlItemElement,{6aaaa30d-54ab-434a-8ae8-6d29a566d870},0,-1,1 +1267,nsIPrefBranchInternal,{d1d412d9-15d6-4a6a-9533-b949dc175ff5},0,-1,1 +1268,nsIDOMSVGPathSegList,{94a6db98-3f34-4529-a35f-89ef49713795},0,-1,1 +1269,nsISupportsPRUint16,{dfacb090-4a1c-11d3-9890-006008962422},0,-1,1 +1270,mozIStorageStatement,{20c45bdd-51d4-4f07-b70e-5feaa6302197},0,-1,1 +1271,nsIStringBundle,{d85a17c2-aa7c-11d2-9b8c-00805f8a16d9},0,-1,1 +1272,nsIDOMLSLoadEvent,{6c16a810-a37d-4859-b557-337341631aee},0,-1,1 +1273,nsIDOMNavigator,{777bd8a1-38c1-4b12-ba8f-ff6c2eb8c56b},0,-1,1 +1274,nsIDOMHTMLVoidCallback,{4a17c0e2-fdd5-4855-a71c-b4c509dffa13},0,-1,1 +1275,nsPIEditorTransaction,{4f18ada2-0ddc-11d5-9d3a-0060b0f8baff},0,-1,1 +1276,nsISearchSubmission,{58e4f602-a7c8-4cd1-9dca-716705e826ef},0,-1,1 +1277,nsIDOMWindowInternal,{c2f4433a-8b4c-4676-ab30-3bffd26fb29e},0,-1,1 +1278,nsIDOMSVGFilterPrimitiveStandardAttributes,{ab68567a-b830-4c46-9f2f-a28513a9e980},0,-1,1 +1279,nsIDOMSVGAnimatedString,{36f18f12-61a9-4529-8fa9-30050bd6ac00},0,-1,1 +1280,nsIDOMOfflineResourceList,{f394a721-66e9-46fc-bb24-b980bb732dd0},0,-1,1 +1281,nsISupportsInterfacePointer,{995ea724-1dd1-11b2-9211-c21bdd3e7ed0},0,-1,1 +1282,nsIFlavorDataProvider,{7e225e5f-711c-11d7-9fae-000393636592},0,-1,1 +1283,nsIDOMSVGSymbolElement,{86092181-a5db-4a89-be03-07dcc14d426e},0,-1,1 +1284,nsIRDFXMLParser,{1831dd2e-1dd2-11b2-bdb3-86b7b50b70b5},0,-1,1 +1285,nsIServerSocket,{a5b64be0-d563-46bb-ae95-132e46fcd42f},0,-1,1 +1286,nsIDOMXULDocument,{d55c39b4-b54a-4df5-9e68-09919e4538f9},0,-1,1 +1287,nsIEditorSpellCheck,{90c93610-c116-44ab-9793-62dccb9f43ce},0,-1,1 +1288,nsIDOMHTMLScriptElement,{a6cf90b1-15b3-11d2-932e-00805f8add32},0,-1,1 +1289,nsIWebBrowserChromeFocus,{d2206418-1dd1-11b2-8e55-acddcd2bcfb8},0,-1,1 +1290,nsIEntityConverter,{d14c7111-55e0-11d3-91d9-00105aa3f7dc},0,-1,1 +1291,nsISimpleEnumerator,{d1899240-f9d2-11d2-bdd6-000064657374},0,-1,1 +1292,nsIScriptableUnicodeConverter_1_9_BRANCH,{f7ed6618-5ff5-4f0b-bb83-48ce63eb289b},0,-1,1 +1293,nsIEmbeddingSiteWindow2,{e932bf55-0a64-4beb-923a-1f32d3661044},0,-1,1 +1294,nsIBufferedOutputStream,{6476378a-da09-11d3-8cda-0060b0fc14a3},0,-1,1 +1295,nsIDocumentEncoder,{f85c5a20-258d-11db-a98b-0800200c9a66},0,-1,1 +1296,nsIChannelEventSink,{6757d790-2916-498e-aaca-6b668a956875},0,-1,1 +1297,nsIXPCComponents_Utils,{da2267f2-d4cc-448f-9d70-1c7fe134d2fe},0,-1,1 +1298,nsINavHistoryContainerResultNode,{f9c8e1c1-e701-44ad-893c-8504c3956929},0,-1,1 +1299,nsIPrintingPrompt,{44e314ca-75b1-4f3d-9553-9b3507912108},0,-1,1 +1300,nsIDOMHTMLOptionElement,{a6cf9092-15b3-11d2-932e-00805f8add32},0,-1,1 +1301,nsISupportsPRInt32,{e36c5250-4a1c-11d3-9890-006008962422},0,-1,1 +1302,nsIDOMWindowUtils_1_9_2,{b0f803f7-98c0-4152-812c-d6678ba23049},0,-1,1 +1303,nsIFrameLoader,{d675c531-6bdc-417c-b176-635060105f07},0,-1,1 +1304,nsIDOMSVGPathSegLinetoVerticalRel,{d3ef2128-8de3-4aac-a6b4-13c7563119a6},0,-1,1 +1305,nsIDOMXULCommandDispatcher,{f3c50361-14fe-11d3-bf87-00105a1b0627},0,-1,1 +1306,nsIDOMGeoGeolocation,{37687daf-b85f-4e4d-8881-85a0ad24cf78},0,-1,1 +1307,nsIX509CertDB,{da48b3c0-1284-11d5-ac67-000064657374},0,-1,1 +1308,nsIDOMRangeException,{0f807301-39d2-11d6-a7f2-8f504ff870dc},0,-1,1 +1309,extIPreference,{2c7462e2-72c2-4473-9007-0e6ae71e23ca},0,-1,1 +1310,nsICryptoHMAC,{8feb4c7c-1641-4a7b-bc6d-1964e2099497},0,-1,1 +1311,nsILineInputStream,{c97b466c-1e6e-4773-a4ab-2b2b3190a7a6},0,-1,1 +1312,nsIWeakReference,{9188bc85-f92e-11d2-81ef-0060083a0bcf},0,-1,1 +1313,nsIGeolocationRequest,{f2aefde1-8e38-48b3-bbb8-bd6c4ae1ac8a},0,-1,1 +1314,nsIAccessibleHyperLink,{38c60bfa-6040-4bfe-93f2-acd6a909bb60},0,-1,1 +1315,nsILoginMetaInfo,{867407d5-10e0-43a0-bc81-a324740534ca},0,-1,1 +1316,nsIForwardIterator,{8da01646-1dd2-11b2-98a7-c7009045be7e},0,-1,1 +1317,inIFlasher,{7b4a099f-6f6e-4565-977b-fb622adbff49},0,-1,1 +1318,nsIBadCertListener2,{2c3d268c-ad82-49f3-99aa-e9ffddd7a0dc},0,-1,1 +1319,nsIDOMClientRectList,{917da19d-62f5-441d-b47e-9e35f05639c9},0,-1,1 +1320,nsIDOMSmartCardEvent,{52bdc7ca-a934-4a40-a2e2-ac83a70b4019},0,-1,1 +1321,nsIXULRuntime,{17311145-97da-49eb-b984-965bdee8879c},0,-1,1 +1322,nsIRemoteService,{a2240f6a-f1e4-4548-9e1a-6f3bc9b2426c},0,-1,1 +1323,nsIDOMXPathResult,{75506f84-b504-11d5-a7f2-ca108ab8b6fc},0,-1,1 +1324,nsIDOMSVGLocatable,{9cf4fc9c-90b2-4d66-88f5-35049b558aee},0,-1,1 +1325,nsIWebBrowserFind,{2f977d44-5485-11d4-87e2-0010a4e75ef2},0,-1,1 +1326,nsICryptoFIPSInfo,{99e81922-7318-4431-b3aa-78b3cb4119bb},0,-1,1 +1327,nsIDOMGeoPositionError,{ad9fa4c8-ec71-4b2d-8294-9adf06ddec32},0,-1,1 +1328,nsICertVerificationResult,{2fd0a785-9f2d-4327-8871-8c3e0783891d},0,-1,1 +1329,nsIRDFService,{bfd05261-834c-11d2-8eac-00805f29f370},0,-1,1 +1330,nsIDOMXULMultiSelectControlElement,{82c72eca-9886-473e-94cd-9de5694b3f88},0,-1,1 +1331,nsIMicrosummaryService,{d58143a2-74fa-4b13-94ed-113af8936d80},0,-1,1 +1332,nsIControllers,{f36e3ec1-9197-4ad8-8d4c-d3b1927fd6df},0,-1,1 +1333,jsdIErrorHook,{cea9ab1a-4b5d-416f-a197-9ffa7046f2ce},0,-1,1 +1334,nsIDOMHTMLInputElement,{a6cf9093-15b3-11d2-932e-00805f8add32},0,-1,1 +1335,mozIStorageStatementCallback,{29383d00-d8c4-4ddd-9f8b-c2feb0f2fcfa},0,-1,1 +1336,nsIDOMSVGGElement,{0bd57cbd-a090-44aa-a61b-2fb876841194},0,-1,1 +1337,nsIDOMPluginArray,{f6134680-f28b-11d2-8360-c90899049c3c},0,-1,1 +1338,nsICipherInfo,{028e2b2a-1f0b-43a4-a1a7-365d2d7f35d0},0,-1,1 +1339,nsIDOMNamedNodeMap,{a6cf907b-15b3-11d2-932e-00805f8add32},0,-1,1 +1340,nsIDOMHTMLBaseFontElement,{a6cf90a6-15b3-11d2-932e-00805f8add32},0,-1,1 +1341,nsIDOMXULCheckboxElement,{5afaba88-1dd2-11b2-9249-dd65a129d0e4},0,-1,1 +1342,nsIDOMHTMLMediaError,{7bd8c29f-8a76-453f-9373-79f820f2dc01},0,-1,1 +1343,nsIFormAutoComplete,{997c0c05-5d1d-47e5-9cbc-765c0b8ec699},0,-1,1 +1344,nsIDOMHTMLDirectoryElement,{a6cf909c-15b3-11d2-932e-00805f8add32},0,-1,1 +1345,nsIBrowserProfileMigrator,{f8365b4a-da55-4e47-be7a-230142360f62},0,-1,1 +1346,nsIDOMSVGSwitchElement,{7676f306-22c9-427e-bd71-2b1315851c93},0,-1,1 +1347,nsIDOMOrientationEvent,{1618546a-c176-40a2-9086-2d973acceeb1},0,-1,1 +1348,nsIURIChecker,{4660c1a1-be2d-4c78-9baf-c22984176c28},0,-1,1 +1349,nsIDOMNSHTMLAreaElement,{3dce9071-f3b9-4280-a6ee-776cdfe3dd9e},0,-1,1 +1350,nsIDOMDataTransfer,{34042440-60a8-4992-ae5c-798e69148955},0,-1,1 +1351,nsIDOMHTMLImageElement,{a6cf90ab-15b3-11d2-932e-00805f8add32},0,-1,1 +1352,nsILocalFileWin,{def24611-88a1-2cac-74fd-4b0b12bcaed5},0,-1,1 +1353,nsIDOMHTMLTextAreaElement,{a6cf9094-15b3-11d2-932e-00805f8add32},0,-1,1 +1354,nsIDOMCommandEvent,{37fb1798-0f76-4870-af6f-0135b4d973c8},0,-1,1 +1355,nsIFeedContainer,{577a1b4c-b3d4-4c76-9cf8-753e6606114f},0,-1,1 +1356,nsIDOMXULButtonElement,{6852d9a6-1dd2-11b2-a29d-cd7977a91b1b},0,-1,1 +1357,nsIXULTemplateQueryProcessor,{970f1c36-5d2e-4cbc-a1cf-e3327b50df71},0,-1,1 +1358,nsIEmbeddingSiteWindow,{3e5432cd-9568-4bd1-8cbe-d50aba110743},0,-1,1 +1359,nsIDOMSVGFEPointLightElement,{557f128a-026b-4fa8-a44c-605df7bfd62e},0,-1,1 +1360,nsIDOMSVGFitToViewBox,{089410f3-9777-44f1-a882-ab4225696434},0,-1,1 +1361,nsISearchableInputStream,{8c39ef62-f7c9-11d4-98f5-001083010e9b},0,-1,1 +1362,nsINavHistoryQuery,{6f5668f0-da8e-4069-a0de-6680e5cd8570},0,-1,1 +1363,nsIXPConnectWrappedNative,{f819a95a-6ab5-4a02-bda6-32861e859581},0,-1,0 +1364,nsIAcceleration,{1b406e32-cf42-471e-a470-6fd600bf4c7b},0,-1,1 +1365,nsIPK11Token,{51191434-1dd2-11b2-a17c-e49c4e99a4e3},0,-1,1 +1366,nsIControllerCommand,{0eae9a46-1dd2-11b2-aca0-9176f05fe9db},0,-1,1 +1367,nsIXSLTProcessorPrivate,{b8d727f7-67f4-4dc1-a318-ec0c87280816},0,-1,1 +1368,nsISessionStartup,{c0b185e7-0d21-46ac-8eee-7b5065ee7ecd},0,-1,1 +1369,nsIDOMNSHTMLAnchorElement2,{d7627eda-6ec0-4326-87c4-c3067fe6e324},0,-1,1 +1370,nsIWebBrowserStream,{86d02f0e-219b-4cfc-9c88-bd98d2cce0b8},0,-1,1 +1371,nsINativeTreeSelection,{1bd59678-5cb3-4316-b246-31a91b19aabe},0,-1,0 +1372,nsINSSCertCache,{1b75bdae-1757-4322-9d1e-cfcaa18cb710},0,-1,1 +1373,nsISocketProviderService,{8f8a23d0-5472-11d3-bbc8-0000861d1237},0,-1,1 +1374,nsIZipReaderCache,{52c45d86-0cc3-11d4-986e-00c04fa0cf4a},0,-1,1 +1375,nsIWebProgressListener2,{dde39de0-e4e0-11da-8ad9-0800200c9a66},0,-1,1 +1376,nsIDOMHTMLFrameElement,{a6cf90b9-15b3-11d2-932e-00805f8add32},0,-1,1 +1377,nsIAuthPrompt,{358089f9-ee4b-4711-82fd-bcd07fc62061},0,-1,1 +1378,jsdINestCallback,{88bea60f-9b5d-4b39-b08b-1c3a278782c6},0,-1,1 +1379,nsIHTTPIndex,{6f2bdbd0-58c3-11d3-be36-00104bde6048},0,-1,1 +1380,nsIDOMDocumentRange,{7b9badc6-c9bc-447a-8670-dbd195aed24b},0,-1,1 +1381,nsICMSMessage,{a4557478-ae16-11d5-ba4b-00108303b117},0,-1,0 +1382,nsIProfileUnlocker,{08923af1-e7a3-4fae-ba02-128502193994},0,-1,1 +1383,nsIDOMNodeIterator,{5af83f50-c8d5-4824-be29-1aa9d640bacb},0,-1,1 +1384,nsIDOMSVGAnimatedPathData,{6ef2b400-dbf4-4c12-8787-fe15caac5648},0,-1,1 +1385,nsIEncodedChannel,{30d7ec3a-f376-4652-9276-3092ec57abb6},0,-1,1 +1386,nsIXPTLoaderSink,{6e48c500-8682-4730-add6-7db693b9e7ba},0,-1,1 +1387,nsIDOMNSHTMLDocument,{79beb289-3644-4b54-9432-9fb993945629},0,-1,1 +1388,nsIAccessibleValue,{42a1e1dc-58cf-419d-bff0-ed3314c70016},0,-1,1 +1389,nsIAtom,{3d1b15b0-93b4-11d1-895b-006008911b81},0,-1,1 +1390,nsIAsyncOutputStream,{beb632d3-d77a-4e90-9134-f9ece69e8200},0,-1,1 +1391,nsIDOMEntityReference,{a6cf907a-15b3-11d2-932e-00805f8add32},0,-1,1 +1392,nsIXTFElementWrapper,{0ad87068-c6fd-4122-a515-ffe8c4773b10},0,-1,1 +1393,nsIJSRuntimeService_MOZILLA_1_9_2,{d23f5479-39a1-4127-8cdd-0f7cb7e8054d},0,-1,0 +1394,nsIDOMSVGRectElement,{1695ca39-e40d-44dc-81db-a51b6fd234fa},0,-1,1 +1395,mozITXTToHTMLConv,{77c0e42a-1dd2-11b2-8ebf-edc6606f2f4b},0,-1,1 +1396,nsIMicrosummaryObserver,{560b0980-be95-47e9-81cc-4428c073127c},0,-1,1 +1397,mozIJSSubScriptLoader,{8792d77e-1dd2-11b2-ac7f-9bc9be4f2916},0,-1,1 +1398,nsIDocShellLoadInfo,{92a0a637-373e-4647-9476-ead11e005c75},0,-1,1 +1399,nsIXPCComponents_Results,{2fc229a0-5860-11d3-9899-006008962422},0,-1,1 +1400,nsIPrintSettings,{343700dd-078b-42b6-a809-b9c1d7e951d0},0,-1,1 +1401,nsIContentViewerEdit,{1691a02f-53b2-4cb8-8769-48e7efc908b8},0,-1,1 +1402,nsISupportsPrimitive,{d0d4b136-1dd1-11b2-9371-f0727ef827c0},0,-1,1 +1403,nsIEditorStyleSheets,{4805e682-49b9-11d3-9ce4-ed60bd6cb5bc},0,-1,1 +1404,rdfISerializer,{f0edfcdd-8bca-4d32-9226-7421001396a4},0,-1,1 +1405,nsIDOMSVGPolygonElement,{9de04775-77c5-48b5-9f4a-8996a936bfb2},0,-1,1 +1406,nsIWritablePropertyBag2,{9cfd1587-360e-4957-a58f-4c2b1c5e7ed9},0,-1,1 +1407,nsIDocumentStateListener,{050cdc00-3b8e-11d3-9ce4-a458f454fcbc},0,-1,1 +1408,nsISHTransaction,{2edf705f-d252-4971-9f09-71dd0f760dc6},0,-1,1 +1409,nsIDOMHTMLIsIndexElement,{a6cf908c-15b3-11d2-932e-00805f8add32},0,-1,1 +1410,nsIASN1Sequence,{b6b957e6-1dd1-11b2-89d7-e30624f50b00},0,-1,1 +1411,nsIDOMHTMLAppletElement,{a6cf90ae-15b3-11d2-932e-00805f8add32},0,-1,1 +1412,nsIDOMToString,{2a72e20f-e337-4822-8994-2e35b5550d03},0,-1,1 +1413,nsIDOMScreen,{77947960-b4af-11d2-bd93-00805f8ae3f4},0,-1,1 +1414,nsICertTreeItem,{d0180863-606e-49e6-8324-cf45ed4dd891},0,-1,1 +1415,extIConsole,{ae8482e0-aa5a-11db-abbd-0800200c9a66},0,-1,1 +1416,nsISAXAttributes,{e347005e-6cd0-11da-be43-001422106990},0,-1,1 +1417,nsIXPConnect,{b76828b8-3ac5-469e-946d-3401c6a2104d},0,-1,0 +1418,nsIDOMSVGPathSegCurvetoCubicAbs,{380afecd-f884-4da7-a0d7-5ffc4531b70b},0,-1,1 +1419,nsIUploadChannel,{ddf633d8-e9a4-439d-ad88-de636fd9bb75},0,-1,1 +1420,nsIAccelerationListener,{3386bed8-7393-4704-8ffc-1eb2c35432ff},0,-1,1 +1421,nsIXPCFunctionThisTranslator,{039ef260-2a0d-11d5-90a7-0010a4e73d9a},0,-1,0 +1422,nsIController,{d5b61b82-1da4-11d3-bf87-00105a1b0627},0,-1,1 +1423,nsIDOMSVGURIReference,{8092b5f3-dc8a-459c-94f1-92f8011f2438},0,-1,1 +1424,nsIDOMStorageEvent,{fc540c28-8edd-4b7a-9c30-8638289b7a7d},0,-1,1 diff --git a/src/test/profile/selenium/ui-map/commons-pageset.xml b/src/test/profile/selenium/ui-map/commons-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..504536de024b8976b0a7f07177c484444f33c868 --- /dev/null +++ b/src/test/profile/selenium/ui-map/commons-pageset.xml @@ -0,0 +1,334 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="dialog" description="Dialog links"> + <xpath-ui-element name="OK" xpath="//div[contains(@class, 'x-window')]//button[text()='OK']" description="a generic OK button in a dialog"/> + <xpath-ui-element name="Okay" xpath="//div[contains(@class, 'b_dialogbox')]//a[.//text()='Ok']" description="a generic Ok button in a dialog"/> + <xpath-ui-element name="Cancel" xpath="//a[.//text()='Cancel']" description="a generic Cancel button in a dialog"/> + <xpath-ui-element name="Yes" xpath="//div[contains(@class, 'b_dialogbox')]//a[.//text()='Yes']" description="a generic Yes button in a dialog"/> + <xpath-ui-element name="No" xpath="//div[contains(@class, 'b_dialogbox')]//a[.//text()='No']" description="a generic No button in a dialog"/> + <xpath-ui-element name="select" xpath="//div[contains(@class,'b_window')]//a[.//text()='Select']" description="The Select element of overlays"></xpath-ui-element> + </pageset> + <pageset name="commons" description="contains links that are used in several places within olat - hence commons"> + <pageset name="usertable" description="generic user table links including import, add users, remove, select all and the individual users in the table"> + <testcase-macro name="newgroupmembers"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="tabs::groups"/> + <selenium command="clickAndWait" target="groups::toolbox_create_projectGroup"/> + <selenium command="type" target="group::content_description_groupDetails_groupName" value="commons-pageset-newgroupmembers-testgroup"/> + <selenium command="clickAndWait" target="commons::flexiForm_finishButton"/> + <selenium command="clickAndWait" target="group::content_members_tabMembers"/> + </testcase-macro> + + <xpath-ui-element name="addUsers" xpath="//a[contains(.//text(),'Add user(s)')]" description="add users, if only one usertable on this page"/> + + <pageset name="owners" description="handles special case of import and addusers button in an owner area"> + <!-- <xpath-ui-element xpath="//fieldset[./legend='Owners']//a[contains(.//text(),'Import')]" name="import" description="import users (Owners) button"/> asa unused --> + <xpath-ui-element name="addUsers" xpath="//fieldset[./legend='Owners']//a[contains(.//text(),'Add user(s)')]" description="import users (Owners) button"></xpath-ui-element> + </pageset> + <pageset name="members" description="handles special case of import and addusers button in an members area"> + <xpath-ui-element name="addUsers" xpath="//fieldset[./legend='Members']//a[contains(.//text(),'Add user(s)')]" description="import users (Members) button"></xpath-ui-element> + </pageset> + <pageset name="participants" description="handles special case of import and addusers button in a participants area"> + <xpath-ui-element name="import" xpath="//fieldset[./legend='Participants']//a[contains(.//text(),'Import')]" description="import users (Participants) button"></xpath-ui-element> + <xpath-ui-element name="addUsers" xpath="//fieldset[./legend='Participants']//a[contains(.//text(),'Add user(s)')]" description="import users (Participants) button"></xpath-ui-element> + <xpath-ui-element xpath="//fieldset[./legend='Participants' and .//a/@class='b_table_download']//input[@value='Remove']" name="remove" description="the remove button"></xpath-ui-element> + <xpath-ui-element xpath="//fieldset[./legend='Participants' and .//a/@class='b_table_download']//a[contains(.//text(),'Select all')]" name="selectAll" description="select-all button"/> + <!-- <xpath-ui-element xpath="//fieldset[./legend='Participants' and .//a/@class='b_table_download']//a[contains(.//text(),'Delete selection')]" name="deleteSelection" description="delete-selection button"/> asa unused --> + </pageset> + <pageset name="waitingList" description="handles special case of import and addusers button in the waiting list area"> + <xpath-ui-element name="selectAll" xpath="//fieldset[./legend='Waiting list' and .//a/@class='b_table_download']//a[contains(.//text(),'Select all')]" description="select-all button"/> + <!-- <xpath-ui-element xpath="//fieldset[./legend='Waiting list' and .//a/@class='b_table_download']//a[contains(.//text(),'Delete selection')]" name="deleteSelection" description="delete-selection button"/> asa unused --> + <xpath-ui-element name="remove" xpath="//fieldset[./legend='Waiting list' and .//a/@class='b_table_download']//input[@value='Remove']" description="the remove button"></xpath-ui-element> + </pageset> + <pageset name="userlist" description="result of a user search operation"> + <xpath-ui-element name="clickUserName" xpath="//div[.//a/@class='b_table_download']//table//tr//td//a[./text()='" + nameOfUser + "']" description="click on a user name in the user table (usually the column titled 'User name')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="checkUsername" xpath="//table//tr[.//td//text()='" + nameOfUser + "']//input[@type='checkbox']" description="check the checkbox of a user in the user table (usually the column titled 'Check')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="selectUserName" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfUser + "']//a[.//text()='Select']" description="click on the 'Selct' link of a particular user in the user table (usually the column titled 'Action')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="selectAll" xpath="//div[.//a/@class='b_table_download']//a[contains(.//text(),'Select all')]" description="select-all button" testcase="newgroupmembers/click(commons::usertable_selectAll)"/> + <!-- <xpath-ui-element xpath="//div[.//a/@class='b_table_download']//a[contains(.//text(),'Delete selection')]" name="deleteSelection" description="delete-selection button" testcase="newgroupmembers/click(commons::usertable_deleteSelection)"/> asa unused --> + </pageset> + <!-- <xpath-ui-element xpath="//fieldset[./legend and .//a/@class='b_table_download']//a[@class='b_table_download']" name="downloadTable" description="the downloda table button"></xpath-ui-element> asa unused --> + <xpath-ui-element name="remove" xpath="//fieldset[./legend and .//a/@class='b_table_download']//button[.//text()='Remove']" description="the remove button"></xpath-ui-element> + <xpath-ui-element name="selectAll" xpath="//fieldset[./legend and .//a/@class='b_table_download']//a[contains(.//text(),'Select all')]" description="select-all button" testcase="newgroupmembers/click(commons::usertable_selectAll)"/> + <xpath-ui-element name="deleteSelection" xpath="//fieldset[./legend and .//a/@class='b_table_download']//a[contains(.//text(),'Delete selection')]" description="delete-selection button" testcase="newgroupmembers/click(commons::usertable_deleteSelection)"/> + + <pageset name="adduser" description="handles special cases of user table within the add user wizard"> + <!-- <xpath-ui-element xpath="//fieldset[./legend='Search along with user attributes' and .//a/@class='b_table_download']//a[@class='b_table_download']" name="downloadTable" description="the downloda table button"></xpath-ui-element> asa unused --> + <xpath-ui-element name="checkUsername" xpath="//fieldset[./legend='Search along with user attributes' and .//a/@name='b_table']//table//tr[.//td//text()='" + nameOfUser + "']//input[@type='checkbox']" description="check the checkbox of a user in the user table (usually the column titled 'Check')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="selectAll" xpath="//fieldset[./legend='Search along with user attributes' and .//a/@name='b_table']//a[contains(.//text(),'Select all')]" description="select-all button"></xpath-ui-element> + <!-- <xpath-ui-element name="deleteSelection" xpath="//fieldset[./legend='Search along with user attributes' and .//a/@name='b_table']//a[contains(.//text(),'Delete selection')]" description="delete-selection button"></xpath-ui-element> asa unused --> + <xpath-ui-element name="choose" xpath="//fieldset[./legend='Search along with user attributes' and .//a/@name='b_table']//input[@value='Choose']" description="choose button"></xpath-ui-element> + + <!-- <xpath-ui-element name="sendEmailHelp" xpath="//fieldset[./legend/text()='E-mail notification']//div[@class='b_contexthelp_wrapper']" description="help in the send-email part of the add user wizard"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='E-mail notification']//select[@name='sendMailSwitchElem']" name="sendEmailSwitch" description="the send-email yes/no switch of the add user wizard"></xpath-ui-element> unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='E-mail notification']//input[@name='subjectElem']" name="emailSubject" description="the email subject of the add user wizard"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='E-mail notification']//textarea[@name='bodyElem']" name="emailBody" description="the email body of the add user wizard"></xpath-ui-element> asa unused --> + <!-- TODO:LD: CHANGE LABEL!!! --> + <xpath-ui-element name="finish" xpath="//fieldset[./legend/text()='E-mail notification']//button[@value='Next']" description="the finish button of the add user wizard"></xpath-ui-element> + <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='E-mail notification']//input[@value='Cancel']" description="the cancel button of the add user wizard"></xpath-ui-element> + <xpath-ui-element name="cancelWizard" xpath="//div[@class='b_button_group']//a[.//text()='Cancel Wizard']" description="cancel wizard button"></xpath-ui-element> + </pageset> + + <!-- <xpath-ui-element xpath="//fieldset[./legend and .//a/@class='b_table_download']//table//tr//td[.//a/text()='" + nameOfUser + "']" name="clickUserName" description="click on a user name in the user table (usually the column titled 'User name')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> asa unused --> + <xpath-ui-element xpath="//fieldset[./legend and .//a/@class='b_table_download']//table//tr[.//td//a/text()='" + nameOfUser + "']//input[@type='checkbox']" name="checkUsername" description="check the checkbox of a user in the user table (usually the column titled 'Check')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="checkUsernameToRemove" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfUser + "']//input[@type='checkbox']" description="check the checkbox of a user in the user table (usually the column titled 'Check')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> + <xpath-ui-element name="removeOwner" xpath="//input[@value='Remove']" description="the Remove button in the dialog Assign owners of this learning resource"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//fieldset[./legend and .//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfUser + "']//a[.//text()='Choose']" name="chooseUserName" description="click on the 'Choose' link of a particular user in the user table (usually the column titled 'Action')"> + <parameter name="nameOfUser" description="the name of the user"/> + </xpath-ui-element> asa unused --> + <xpath-ui-element name="sendUserDeletionEmail" xpath="//input[@value='Send e-mail regarding the deletion of user accounts.']" description="Send e-mail regarding the deletion of user accounts input"></xpath-ui-element> + </pageset> + <pageset name="importUsersWizard" description="the import users wizard"> + <xpath-ui-element xpath="//form[@name='usersform']//textarea[@name='addusers']" name="user names textarea" description="the user names textarea"></xpath-ui-element> + </pageset> + <pageset name="createGroup" description="form fields create group"> + <!-- <xpath-ui-element xpath="//form[@name='createBuddygroupForm']//input[@value='Save']" name="save" description="save button create group"></xpath-ui-element> + <xpath-ui-element xpath="//form[@name='createBuddygroupForm']//input[@value='Cancel']" name="cancel" description="cancel button create group"></xpath-ui-element> asa unused --> + </pageset> + <pageset name="searchUsers" description="the Other users section under the home tab"> + <default-testcase testcase="login/home::menu_otherUsers" final-command="type(anything)" /> + <!-- <xpath-ui-element name="autoCompleter" xpath="//fieldset[./legend/text()='Search combined with auto-completion']//input[@class='b_form_auto_completer_input']" description="input field called 'search for olat user names, first name, last name or email'" /> asa unused --> + <!--<xpath-ui-element name="userName" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='login']" description="input field 'user name'" /> unused --> + <!-- <xpath-ui-element name="firstName" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='firstName']" description="input field 'first name'" /> + <xpath-ui-element name="lastName" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='lastName']" description="input field 'last name'" /> + <xpath-ui-element name="email" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='email']" description="input field 'email'" /> + <xpath-ui-element name="institutionalName" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='institutionalName']" description="input field 'institution'" /> + <xpath-ui-element name="institutionalUserIdentifier" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='institutionalUserIdentifier']" description="input field 'institution identifier'" /> + <xpath-ui-element name="institutionalEmail" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@id='institutionalEmail']" description="input field 'institutional email'" /> asa unused --> + <!--<xpath-ui-element name="search" xpath="//fieldset[./legend/text()='Search along with user attributes']//input[@value='Search']" description="the search button" testcase="login/home::menu_otherUsers/type(commons::searchUsers_userName,foo)/commons::searchUsers_search" /> unused --> + </pageset> + + <!-- todo: testcase --> + <xpath-ui-element name="start" xpath="//div[@class='b_button_group']//a[@class='b_button'][contains(descendant::text(), 'Start')]" description="Click 'Start' button"/> + <xpath-ui-element name="save" xpath="//div[@class='b_button_group']//button[@value='Save']" description="Save button"/> + <xpath-ui-element name="cancelButton" xpath="//div[@class='b_button_group']//button[@value='Cancel']" description="cancel button"/> + <xpath-ui-element name="saveInput" xpath="//div[@class='b_button_group']//input[@value='Save']" description="save form input"/> + <xpath-ui-element name="saveLink" xpath="//div[@class='b_button_group']//a[//text()='Save']" description="save link"></xpath-ui-element> + <xpath-ui-element name="anyLink" xpath="//a[contains(.//text(),'" + linkText + "')]" description="a generic link with any identified by its label text"> + <parameter name="linkText" description="the text of the label"/> + </xpath-ui-element> + <pageset name="tinyMce" description="RichtTextElement"> + <xpath-ui-element name="styledTextArea" xpath="//body[@id='tinymce']" description="styled text area in iframe"/> + <xpath-ui-element name="insertEditImage" xpath="//a[@title='Insert/edit image']" description="insert edit image"/> + <xpath-ui-element name="browse" xpath="//a[@id='srcbrowser_link']" description="browse image"></xpath-ui-element> + </pageset> + <pageset name="flexiForm" description="flexiforms elements"> + <xpath-ui-element name="labeledTextInput" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='" + formElementLabel + "']//div[@class='b_form_element']//input[@type='text']" description="text form element with the given label"> + <parameter name="formElementLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="labeledPasswordInput" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='" + formElementLabel + "']//div[@class='b_form_element']//input[@type='password']" description="password form element with the given label"> + <parameter name="formElementLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="labeledTextArea" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='" + formElementLabel + "']//div[@class='b_form_element']//textarea" description="text area form element with the given label"> + <parameter name="formElementLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="labeledCheckbox" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='" + formElementLabel + "']//div[@class='b_form_element']//input[@type='checkbox']" description="checkbox form element with the given label"> + <parameter name="formElementLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="disabledTextInput" xpath="//div[@class='b_form_element']//input[@value='" + inputValue + "']" description="disabled text form element with the given value"> + <parameter name="inputValue" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="disabledLabeledTextInput" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='" + formElementLabel + "']//div[@class='b_form_element']//input[@disabled='disabled']" description="disabled text form element with the given label"> + <parameter name="formElementLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="finishButton" xpath="//div[@class='b_form_element']//button[@value='Finish']" description="the finish button of the flexi form"/> + <xpath-ui-element name="saveButton" xpath="//div[@class='b_form_element']//button[@value='Save']" description="the save button of the flexi form"/> + <xpath-ui-element name="genericButton" xpath="//div[@class='b_form_element']//button[@value='" + buttonLabel + "']" description="button with a given label"> + <parameter name="buttonLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="genericLink" xpath="//div[@class='b_form_element']//a[.//text()='" + buttonLabel + "']" description="link of a button class with a given label"> + <parameter name="buttonLabel" description="the label of the form element"/> + </xpath-ui-element> + <xpath-ui-element name="saveButtonVertical" xpath="//div[@class='b_form_element b_form_vertical']//button[@value='Save']" description="the save button of the flexi form, vertical layout"/> + <xpath-ui-element name="createButton" xpath="//div[@class='b_form_element']//button[@value='Create']" description="the Create button of the flexi form"/> + <xpath-ui-element name="formErrorMsg" xpath="//div[@class='b_form_error_msg']" description="form error message, e.g. at invalid input"></xpath-ui-element> + <xpath-ui-element name="cancelButton" xpath="//button[.//text()='Cancel']" description="cancel button"></xpath-ui-element> + + <pageset name="wizzard" description="the flexiform wizzard (steps)"> + <link-ui-element name="next" link="Next" description="The Next button"/> + <link-ui-element name="back" link="Back" description="The Back button"/> + <link-ui-element name="finish" link="Finish" description="The Finish button"/> + <link-ui-element name="cancel" link="Cancel" description="The Cancel button"/> + <xpath-ui-element name="close" xpath="//a[contains(@class, 'b_link_close')]" description="The close icon"/> + </pageset> + </pageset> + + <pageset name="table" description="a table"> + <xpath-ui-element name="showAll" xpath="//div[@class='b_table_page_all']//a[./text()='[Show all]']" description="the [Show all] link"/> + <xpath-ui-element name="selectNextPage" xpath="//div[@class='b_table_page']/a[@class='b_table_forward']" description="click on forward button in table pagination"></xpath-ui-element> + </pageset> + <xpath-ui-element name="backLink" xpath="//a[@class='b_link_back']" description="back link"></xpath-ui-element> + </pageset> + + <pageset name="wiki" description="the wiki module"> + <pageset name="sideNavigation" description="wiki side navigation"> + <xpath-ui-element name="index" xpath="//fieldset/legend[.//text()='Navigation']/..//a[.//text()='Index']" description="Wiki navigation: Index page" /> + <xpath-ui-element name="from-a-z" xpath="//fieldset/legend[.//text()='Navigation']/..//a[.//text()='From A-Z']" description="Wiki navigation: From A-Z" /> + <xpath-ui-element name="clickAWikiPage" xpath="//div[@class='o_wikimod-article-box']//a[./text()='"+nameOfWikiPage+"']" description="the name of the wiki page to click"> + <parameter name="nameOfWikiPage" description="the name of the wiki page"/> + </xpath-ui-element> + + <!-- <xpath-ui-element name="recentChanges" xpath="//fieldset/legend[.//text()='Navigation']/..//a[contains(.//text(),'Recent')]" description="Wiki navigation: Recent changes" /> asa unused --> + <xpath-ui-element name="editWikiMenu" xpath="//fieldset/legend[.//text()='Wiki menu']/..//a[.//text()='Modify']" description="Wiki navigation: Edit wiki menu" /> + <xpath-ui-element name="createInput" xpath="//fieldset[legend[contains(.//text(),'Create article')]]//form//input[@type='text']" description="Wiki navigation: Create article input field" /> + <xpath-ui-element name="createButton" xpath="//fieldset[legend[contains(.//text(),'Create article')]]//form//button[@value='Create']" description="Create article button"></xpath-ui-element> + <xpath-ui-element name="searchInput" xpath="//fieldset[legend[contains(.//text(),'Search')]]//form//input[@type='text']" description="Wiki navigation: Search article input field" /> + <xpath-ui-element name="searchButton" xpath="//fieldset[legend[contains(.//text(),'Search')]]//form//a[.//text()='Search']" description="search button"></xpath-ui-element> + <!-- <xpath-ui-element name="export" xpath="//fieldset/legend[.//text()='Tools']/..//a[.//text()='Export as CP']" description="Wiki Tools: Export" /> asa unused --> + </pageset> + <pageset name="topNavigation" description=""> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_wrapper']//a[.//text()='Article']" + name="article" description="article tab" /> + <!-- <xpath-ui-element xpath="//div[@class='b_tabbedpane_wrapper']//a[.//text()='Discussion']" + name="discussion" description="discussion tab" /> asa unused --> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_wrapper']//a[.//text()='Edit page']" + name="editPage" description="edit page tab" /> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_wrapper']//a[.//text()='Versions/authors']" + name="versions" description="versions tab" /> + </pageset> + <pageset name="edit" description="wiki edit view"> + <xpath-ui-element name="editFormTextarea" xpath="//div[@class='o_wikimod_editform_wrapper']//textarea" + description="the wiki edit form text area" /> + <!-- <xpath-ui-element name="editFormSaveButton" xpath="//form[@name='wikieditform']//input[@type='submit'][@value='Save']" + description="the wiki edit form save button" /> asa unused --> + <xpath-ui-element name="deletePage" xpath="//div[./h1/@class='o_wikimod_heading']//a[.//text()='Delete page']" + description="the delete page button" /> + <!-- <xpath-ui-element name="insertLinkButton" xpath="//div[@class='o_wikimod_linkchooser']//input[@value='Insert link']" + description="the insert button for links" /> asa unused --> + <xpath-ui-element name="insertFileButton" xpath="//div[@class='o_wikimod_filechooser']//input[@value='Insert file']" + description="the insert button for files" /> + <xpath-ui-element name="uploadFileButton" xpath="//a[@id='o_wikimod_uploaderOpener']/b" + description="the upload button for files" /> + </pageset> + <pageset name="article" description="wiki article view"> + <link-ui-element name="testLink" description="create a wiki page with name test" link="test"/> + <!-- <xpath-ui-element xpath="//div[@class='o_wikimod-article-box']" name="articleBox" description="wiki article box" /> asa unused --> + </pageset> + <pageset name="versions" description="versions view"> + <link-ui-element name="compare" description="compare version 0 with 1" link="0 to 1"/> + </pageset> + </pageset> + <pageset name="overlay" description="overlay specific elements"> + <xpath-ui-element xpath="//a[@class='b_link_close']" name="overlayClose" description="closes an overlay" /> + </pageset> + + <pageset name="courseChat" description="the groupchat which works with external chat server"> + <xpath-ui-element name="openCourseChat" xpath="//a[@class='b_toolbox_link' and contains(./span/text(), 'course chat')]" + description="open the course chat window" /> + <xpath-ui-element name="withinCourseChat" xpath="//a[@class='b_toolbox_link' and contains(.//text(), 'Enter course chat')]" description="within course chat"/> + <xpath-ui-element name="toggleAnonymous" xpath="//form//input[@name='toggle']" + description="toggle from anonymous to username" /> + <xpath-ui-element name="sendMsgInputField" xpath="//div[@class='o_groupchat_chat_form']//form//input[@type='text']" + description="send message input field" /> + <xpath-ui-element name="labeledSendMsgInputField" xpath="//div[@class=' x-window x-window-plain x-resizable-pinned'][descendant::text()='" + label + "']//div[@class='o_groupchat_chat_form']//form//input[@type='text']" + description="send message input field" > + <parameter name="label" description="chat room label"/> + </xpath-ui-element> + <xpath-ui-element name="sendMsgButton" xpath="//div[@class='o_groupchat_chat_form']//form//a[contains(@class, 'b_button')]" + description="the send button " /> + <xpath-ui-element name="labeledSendMsgButton" xpath="//div[@class=' x-window x-window-plain x-resizable-pinned'][descendant::text()='" + label + "']//div[@class='o_groupchat_chat_form']//form//a[contains(@class, 'b_button')]" + description="the send button" > + <parameter name="label" description="chat room label"/> + </xpath-ui-element> + <xpath-ui-element name="participant" xpath="//div[@class='o_groupchat_roster']//li[contains(.//text(),'" + participantName + "')]" description="participant in the chatroom"> + <parameter name="participantName" description="participant username or partial label of a user - e.g. anonym"/> + <!-- <parameter name="chatroomLabel" description="chatroomLabel"></parameter> --> + </xpath-ui-element> + </pageset> + <pageset name="buddiesChat" description="buddies chat"> + <xpath-ui-element name="closeExtWindow" xpath="//div[contains(@class, 'x-window')]//div[contains(@class, 'x-tool-close')]" + description="closes the floating window"/> + <xpath-ui-element name="closeLabeledExtWindow" xpath="//div[@class=' x-window x-window-plain x-resizable-pinned'][descendant::text()='" + label + "']//div[contains(@class, 'x-window')]//div[contains(@class, 'x-tool-close')]" + description="closes the floating window"> + <parameter name="label" description="chat room label"/> + </xpath-ui-element> + <xpath-ui-element name="openStatusChanger" xpath="//div[@id='b_topnav']//a[contains(@href, 'cmd.status')]" + description="opens the status changer window" /> + <xpath-ui-element name="openOnlineUserList" xpath="//div[@id='b_footer_user']//a[contains(.//text(), 'People')]" description="xy People are online - left, down side of the page"/> + <xpath-ui-element name="showOnlineBuddies" xpath="//li[@id='o_topnav_imclient']//a[@class='']" description="show online buddies"/> + <xpath-ui-element name="onlineBuddy" xpath="//a[@class='o_instantmessaging_available_icon' and contains(.//text(), '" + fullName + "')]" description="online buddy"> + <parameter name="fullName" description="user first and lastname"></parameter> + </xpath-ui-element> + <xpath-ui-element name="sendMsgInputField" xpath="//div[@class='o_instantmessaging_chat_form']//form//input[@type='text']" description="input chat message field"/> + <xpath-ui-element name="sendMsgButton" xpath="//div[@class='o_instantmessaging_chat_form']//form//a[contains(@class, 'b_button')]" + description="the send button " /> + </pageset> + <pageset name="projectGroupChat" description="chat in project groups"> + <xpath-ui-element name="enterChatroom" xpath="//a[contains(.//text(), 'Enter chatroom')]" description="enter chatroom button for the chat menu item of a project group"/> + </pageset> + + + <pageset name="windowTopNav" description="Elements in the top navigation of any OLAT window"> + <!-- <xpath-ui-element xpath="//li[@id='o_topnav_close']//a" + name="closeWindow" description="close the auxiliary window" /> asa unused --> + </pageset> + + <pageset name="briefCase" description="everything in the briefcase"> + <xpath-ui-element name="clickBriefcaseEntry" xpath="//table[@class='b_briefcase_filetable']//td[@class='b_first_child']/a[.//text()='" + linkText + "']" + description="Click on a folder- or file name in the briefcase"> + <parameter name="linkText" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="selectBriefcaseCheckBox" xpath="//table[@class='b_briefcase_filetable']//td[@class='b_first_child']/input[@value='" + linkText + "']" + description="Click on a check box in the briefcase"> + <parameter name="linkText" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="editMetadata" xpath="//table[@class='b_briefcase_filetable']//td[@class='b_first_child']/input[@value='" + linkText + "']/../..//td[@class='b_last_child']//a[@class=' b_small_icon b_briefcase_edit_meta_icon']" description="edit metadata for a folder entry"> + <parameter name="linkText" description="folder or file name"></parameter> + </xpath-ui-element> + <xpath-ui-element name="editFile" xpath="//table[@class='b_briefcase_filetable']//td[@class='b_first_child']/input[@value='" + linkText + "']/../..//td[@class='b_last_child']//a[@class='b_small_icon b_briefcase_edit_file_icon']" description="edit file"> + <parameter name="linkText" description="folder or file name"></parameter> + </xpath-ui-element> + <xpath-ui-element name="buttonDelete" xpath="//div[@class='b_briefcase_commandbuttons b_button_group']/input[@name='.actiondel']" + description="Click on the Delete button"/> + <!-- <xpath-ui-element name="buttonMove" xpath="//div[@class='b_briefcase_commandbuttons b_button_group']/input[@name='.actionmove']" + description="Click on the Move button"/> + <xpath-ui-element name="buttonCopy" xpath="//div[@class='b_briefcase_commandbuttons b_button_group']/input[@name='.actioncopy']" + description="Click on the Copy button"/> asa unused --> + <xpath-ui-element name="buttonZip" xpath="//div[@class='b_briefcase_commandbuttons b_button_group']/input[@name='.actionzip']" + description="Click on the Zip button"/> + <!-- <xpath-ui-element name="buttonUnzip" xpath="//div[@class='b_briefcase_commandbuttons b_button_group']/input[@name='.actionunzip']" + description="Click on the Unzip button"/> asa unused --> + <xpath-ui-element name="uploadFile" xpath="//div[@class='b_briefcase_createactions b_clearfix']//a[.//text()='Upload file']" + description="Link to upload a file"/> + <xpath-ui-element name="createFolder" xpath="//div[@class='b_briefcase_createactions b_clearfix']//a[.//text()='Create folder']" + description="Link to create a folder"/> + <xpath-ui-element name="createFile" xpath="//div[@class='b_briefcase_createactions b_clearfix']//a[.//text()='Create document']" + description="Link to create a file"/> + <xpath-ui-element name="createFileName" xpath="//div[.//text()='Create new document']//div[@class='b_form_element' and .//text()='index.html, info.txt, mystyles.css']//input[@type='text']" + description="input field for the new file name"/> + <xpath-ui-element name="htmlEditorSave" xpath="//div[@id='b_htmleditor_save']//a[.//text()='Save']" description="save edited text at create file"></xpath-ui-element> + <xpath-ui-element name="htmlEditorSaveAndClose" xpath="//div[@id='b_htmleditor_save']//a[.//text()='Save and close']" description="save edited text at create file, and close overlay"></xpath-ui-element> + <!-- <xpath-ui-element name="editQuota" xpath="//a[.//text()='Edit quota']" description="edit quota button"></xpath-ui-element> asa unused --> + <xpath-ui-element name="folderComponent" xpath="//div[@class='b_briefcase_foldercomp']" description="folder component div"></xpath-ui-element> + <xpath-ui-element name="selectAll" xpath="//div[@class='b_togglecheck']//a[.//input[@checked='checked']]" description="select all from folder filetable"></xpath-ui-element> + <xpath-ui-element name="zipFiles" xpath="//button[@value='Zip files']" description="zip files button"></xpath-ui-element> + </pageset> + + <pageset name="search" description="search"> + <xpath-ui-element name="topnavSearchInput" xpath="//li[@id='o_topnav_search']//div[@class='b_form_element b_form_horizontal']//input" description="topnav search input "/> + <xpath-ui-element name="topnavSubmitSearch" xpath="//li[@id='o_topnav_search']//div[@class='b_form_element b_form_horizontal']//a" description="topnav search sumbit button"></xpath-ui-element> + <xpath-ui-element name="searchFormInput" xpath="//div[@id='o_local_fulltextsearch']//div[@class='b_form_element b_form_horizontal']//input[@type='text']" description="Simple Search form - input element"></xpath-ui-element> + <xpath-ui-element name="searchButton" xpath="//div[@id='o_local_fulltextsearch']//div[@class='b_form_element b_form_horizontal']//a[contains(.//text(), 'Search')]" description="Simple Search button"></xpath-ui-element> + </pageset> + + <pageset name="upload" description="Upload file"> + <xpath-ui-element name="submit" xpath="//div[@class='b_button_group']//button[@value='Upload']" description="Submit button on upload resource"/> + <xpath-ui-element name="fileChooser" xpath="//div[@class='b_fileinput']//input[@class='b_fileinput_realchooser']" description="the file choose input field"/> + </pageset> +</ui-map-include> diff --git a/src/test/profile/selenium/ui-map/course-pageset.xml b/src/test/profile/selenium/ui-map/course-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..dade3986e76e074d8c5d8338912a6caf8d5a57af --- /dev/null +++ b/src/test/profile/selenium/ui-map/course-pageset.xml @@ -0,0 +1,322 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + + <pageset name="course" description="An opened course"> + + <pageset name="menu" description="the left hand menu"> + <xpath-ui-element name="root" + xpath="//a[contains(.//text(),'" + nameOfCourse + "')]" + description="The root link (named after the short title of the course, with tooltip title)"> + <parameter name="nameOfCourse" description="the name of the course"> + <defaultValue value="Demo course wiki"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="link" xpath="//div[@class='b_tree']//a[.//text()='" + link + "']" description="a course node link in the courserun, containing the linkText" > + <parameter name="link" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="forum" + xpath="//div[@class='b_tree']//a[descendant::text()='Forum']" + description="Course node 'Forum'"/> + <xpath-ui-element name="structureNode" + xpath="//div[@class='b_tree']//a[contains(descendant::text(), 'Structure')]" + description="Course node 'Structure'"/> + <!-- ld: courseNode replaces the structureNode and forum, fix test cases before removal! --> + <xpath-ui-element name="courseNode" + xpath="//div[@class='b_tree']//a[contains(descendant::text(), '" + titleOfNode + "')]" + description="Click on the course node with the given title"> + <parameter name="titleOfNode" description="the title of the course node"> + <defaultValue value="Structure"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="positionedCourseElem" xpath="//div[@class='b_tree']//ul[contains(@class,'b_tree_l1')]/li[" + index + "]//a" description="course element identified by the index value"> + <parameter name="index" description="root's child index"/> + </xpath-ui-element> + </pageset> + + <!--TODO se evtl. xpath-ui-element links?--> + + <pageset name="toolbox" description="the toolbox area to the right"> + <pageset name="courseTools" description="the course tools toolbox"> + <link-ui-element name="courseEditor" link="Course editor" + description="Course editor Link"/> + <link-ui-element name="groupManagement" link="Group management" + description="Group Management link"/> + <link-ui-element name="rightsManagement" link="Rights management" + description="Rights Management link"/> + <!-- <link-ui-element name="archiveTool" link="Archive tool" + description="Archive Tool link"/> asa unused --> + <link-ui-element name="assessmentTool" link="Assessment tool" + description="Assessment tool link"/> + </pageset> + + <pageset name="generalTools" description="general course tools toolbox"> + <!-- <link-ui-element name="calendar" link="Calendar" + description="Calendar link"/> asa unused --> + <!-- <link-ui-element name="glossary" link="Glossary" + description="Glossary link"/> asa unused --> + <link-ui-element name="detailedView" link="Detailed view" + description="Detailed view link"/> + <!-- <link-ui-element name="personalNotes" link="Personal notes" + description="Personal notes link"/> asa unused --> + <link-ui-element name="setBookmark" link="Set bookmark" + description="Set bookmark link"/> + <!-- <xpath-ui-element xpath="//div[@class='b_toolbox'][descendant::text()='General']//a[.//text()='Enter course chat...']" + name="enterCourseChat" description="the Enter Course Chat link"/> asa unused --> + </pageset> + + <pageset name="myGroupsTools" description="group links toolbox"> + <xpath-ui-element name="tutoredGroups" + xpath="//div[@class='b_toolbox']//a[@class='b_toolbox_link' and descendant::text()='" + nameOfGroup + "']" + description="tutored groups"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + <xpath-ui-element name="myLearningGroups" + xpath="//div[@class='b_toolbox'][descendant::text()='My learning groups']//a[contains(descendant::text(), '" + nameOfGroup + "')]" + description="my learning groups"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + </pageset> + </pageset> + + <pageset name="content" description="the (center) content area"> + <xpath-ui-element name="contentElement" xpath="//div[@class='o_course_run']" description="content of the course element"/> + <pageset name="forum" description="forum in content area"> + <xpath-ui-element name="displayForum" + xpath="//div[@class='b_button_group']//a[.//text()='Display forum']" + description="Display forum after node selection"/> + + <xpath-ui-element name="newTopic" xpath="link=Open new topic" + description="Open new topic"/> + <!-- <xpath-ui-element name="archiveForum" xpath="link=Archive forum" + description="Archive forum"/> asa unused --> + <xpath-ui-element name="replyWithQuotation" xpath="link=Reply with quotation" + description="Reply with quot. to forum message"/> + <xpath-ui-element name="replyWithoutQuotation" xpath="link=Reply without quotation" + description="Reply w/o quot. to forum message"/> + <xpath-ui-element name="delete" xpath="link=Delete" + description="Delete forum message"/> + <xpath-ui-element name="deleteYes" xpath="link=Yes" + description="Confirm Yes delete forum message"/> + <!-- <xpath-ui-element name="deleteNo" xpath="link=No" + description="Confirm No delete forum message"/> asa unused --> + <xpath-ui-element name="edit" xpath="link=Edit" description="Edit forum message"/> + <xpath-ui-element name="deleteFile" xpath="//table//tr/td[contains(descendant::text(), '" + nameOfFile + "')]/../td//a[.//text()='Delete']" + description="delete file from forum message"> + <parameter name="nameOfFile" description="the name of the file"/> + </xpath-ui-element> + <xpath-ui-element name="typeMsgTitle" + xpath="//div[@class='b_form_element b_form_vertical']//input[@type='text']" + description="Forum - enter message title text"/> + <xpath-ui-element name="clickMsgBody" + xpath="//body[@id='tinymce']" + description="Forum - enter message body text"/> + <!-- <xpath-ui-element name="cancel" + xpath="//div[@class='b_button_group']//input[@value='Cancel']" + description="Forum - cancel message"/> asa unused --> + <xpath-ui-element name="save" + xpath="//div[@class='b_button_group']//button[@value='Save']" + description="Forum - save message"/> + <xpath-ui-element name="collectAsArtefact" xpath="//*[ @class and contains( concat( ' ', normalize-space(@class), ' ' ), ' b_eportfolio_add ' ) ]" + description="Collect post as artefact for ePortfolio"/> + <!-- <xpath-ui-element name="archiveThread" xpath="link=Archive thread" + description="Archive forum thread"/> asa unused --> + <!-- <xpath-ui-element name="closeDiscussion" xpath="link=Close discussion" + description="Close discussion"/> asa unused --> + <!-- <xpath-ui-element name="hideDiscussion" xpath="link=Hide discussion" + description="Hide discussion"/> asa unused --> + <!-- <xpath-ui-element name="showDiscussion" xpath="link=Show discussion" + description="Show discussion"/> asa unused --> + + <xpath-ui-element name="viewTopic" + xpath="//form[contains(@name, 'tb_ms')]//a[.//text()='"+nameOfTopic+"']" + description="Click on discussion topic"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <!--TODO se + <xpath-ui-element name="showPreview" xpath="link=Show preview" description="Show preview of forum message"/> + --> + + </pageset> + + <pageset name="enrollment" description="the entrolment content area"> + <xpath-ui-element name="enrolOnGroup" + xpath="//form/div/table/tbody/tr[./td//text()='" + nameOfGroup + "']//a[.//text()='Enrol']" + description="enrol on a particular group"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + <xpath-ui-element name="enrolledOrNot" + xpath="//form/div/table/tbody/tr[./td//text()='" + nameOfGroup + "']//td[.//text()='enrolled' or .//text()='Not enrolled']" + description="enrolled on a particular group"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + <xpath-ui-element name="cancelEnrolment" + xpath="//form/div/table/tbody/tr[./td//text()='" + nameOfGroup + "']//a[contains(.//text(),'Cancel')]" + description="cancel enrolment on a particular group"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + <xpath-ui-element name="enrolmentType" + xpath="//div[@class='o_course_run_statusinfo' or @class='o_course_run_groupinfo']" + description="Course element of the type Enrolment - info"/> + + </pageset> + <pageset name="fileDialog" description="the file dialog content area"> + <xpath-ui-element + xpath="//div[@class='b_titled_wrapper o_course_run']//a[.//text()='Upload file']" + name="uploadFile" description="the upload button for files"> + </xpath-ui-element> + </pageset> + <!-- new for 6.3--> + <pageset name="blog" description="the blog content area"> + <!-- links in blog run--> + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Edit blog']" name="editBlog" description="the edit blog button"/> + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Create your own entries']" name="createOwnEntries" description="the create own entries button"/> + <xpath-ui-element xpath="//div[@class='b_button']//a[.//text()='Include an external blog already existing']" name="includeExtBlog" description="the include an external blog button"/> + <xpath-ui-element xpath="//div[@class='b_form_element']//a[.//text()='URL']" name="blogURL" description="URL field"/> + + <xpath-ui-element xpath="//div[@class='b_form_element']//a[.//text()='Title']" name="entryTitle" description="entry title field"/> + <!-- LD: how to define these two fields? + <xpath-ui-element xpath="'Description'" name="entryDescription" description="entry description field"/> + <xpath-ui-element xpath="'Content'" name="entryContent" description="entry content field"/> + --> + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Publish']" name="publishEntry" description="the publish entry button"/> + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Save draft']" name="saveDraft" description="the save draft button"/> + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Cancel']" name="cancel" description="the cancel button"/> + + + <xpath-ui-element xpath="//div[@class='b_button_group']//a[.//text()='Create new entry']" name="createEntry" description="the create new entry button"/> + <xpath-ui-element xpath="//div[@class='b_button b_xsmall']//a[.//text()='Edit entry']" name="editEntry" description="the edit entry button"/> + <xpath-ui-element xpath="//div[@class='b_button_b_xsmall']//a[.//text()='Delete']" name="deleteEntry" description="the delete button"/> + <!-- LD: how to define these links? + <xpath-ui-element xpath="'Read more']" name="readMore" description="the read more link"/> + // ld: comment function same for podcast, xpath Comments(0) with counter of number of comments + <xpath-ui-element xpath="'Comments']" name="comments" description="the comments link"/> + <xpath-ui-element xpath="'Add your comment']" name="addComment" description="the add your comment link"/> + --> + <xpath-ui-element xpath="//div[@class='b_button_b_xsmall']//a[.//text()='Reply']" name="reply" description="the reply button"/> + <xpath-ui-element xpath="//div[@class='b_button_b_xsmall']//a[.//text()='Delete']" name="deleteComment" description="the delete button"/> + <!-- LD: im ui:commons? + <xpath-ui-element xpath="'Save']" name="saveComment" description="the save comment button"/> + <xpath-ui-element xpath="'Cancel']" name="cancelComment" description="the cancel comment button"/> + --> + </pageset> + + <pageset name="scorm" description="scorm"> + <xpath-ui-element name="scormPreview" + xpath="//div[@class='b_form_element']//button[@value='Show SCORM learning content']" + description="show SCORM content button"> + </xpath-ui-element> + <link-ui-element name="back" link="Back" description="The Back button"/> + </pageset> + <pageset name="assessment" description="assessment course element"> + <xpath-ui-element name="summaryOfScore" + xpath="//div[@class='o_course_run_scoreinfo' and .//text()='Summary of score']" + description="Summary of score title"/> + </pageset> + <pageset name="lti" description="lti xpaths"> + <xpath-ui-element name="launch" xpath="//input[@name='ext_basiclti_submit']" description="launch button"/> + </pageset> + <!-- for test see qti-pageset.xml--> + <xpath-ui-element name="passedFailedStatus" + xpath="//div[@class='o_course_run_scoreinfo']//td[contains(descendant::text(), 'Status')]/../td[2]/span/text()" + description="course scoreEvaluation info: Passed/Failed"/> + </pageset> + + <pageset name="assessment" description="AssessmentTool links"> + <xpath-ui-element name="tableFilterForm" xpath="//div[@class='b_table_filter']//form[@name='tablefilter']" description="The Assessment overview table filter"/> + <xpath-ui-element name="selectType" + xpath="//div[@class='b_tree']//a[./text()='" + text + "']" + description="select the left hand menu link with the given text"> + <parameter name="text" description="the text of the left hand menu link"> + <defaultValue value="As per user"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="selectUser" + xpath="//table//a[./text()='" + username + "']" + description="select the user with the given username"> + <parameter name="username" description="username"> + <defaultValue value="test"/> + </parameter> + </xpath-ui-element> + <!-- It is assumed that each course element has a unique title within the current course --> + <xpath-ui-element name="scoreInTable" + xpath="//td[contains(descendant::text(), '" + title + "')]/../td[4]/text()" + description="score xpath for the specified test course element in the assessment overview"> + <parameter name="title" description="the title of the test course node"> + <defaultValue value="Test"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="attemptsInTable" + xpath="//td[contains(descendant::text(), '" + title + "')]/../td[3]/text()" + description="attempts xpath for the specified test course element in the assessment overview"> + <parameter name="title" description="the title of the test course node"> + <defaultValue value="Test"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="passedStatusInTable" + xpath="//td[contains(descendant::text(), '" + title + "')]/../td[5]//text()" + description="passed/failed xpath for the specified test course element in the assessment overview"> + <parameter name="title" description="the title of the test course node"> + <defaultValue value="Test"/> + </parameter> + </xpath-ui-element> + + <xpath-ui-element name="selectAssessmentCourseNode" + xpath="//td[contains(descendant::text(), '" + title + "')]/../td[6]/a[.//text()='Select']" + description="'Select' link of the asssessment course node"> + <parameter name="title" description="the title of the test course node"> + <defaultValue value="Bewertung"/> + </parameter> + </xpath-ui-element> + <!-- AssessementForm start --> + <xpath-ui-element name="setPassedNoInfo" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Passed']//div[@class='b_form_element']//input[@name='passed' and @value='undefined']" + description="'Passed' no information"/> + <xpath-ui-element name="setPassedYes" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Passed']//div[@class='b_form_element']//input[@name='passed' and @value='true']" + description="'Passed' Yes"/> + <xpath-ui-element name="setPassedNo" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Passed']//div[@class='b_form_element']//input[@name='passed' and @value='false']" + description="'Passed' no information"/> + <xpath-ui-element name="minMaxScore" + xpath="//div[@class='b_form_element_wrapper b_clearfix' and .//text()='" + title + "']//div[@class='b_form_element']//span/text()" + description="Minimum/maximum score in AssessmentForm"> + <parameter name="title" description="the label: Minimum score or Maximum score"> + <defaultValue value="Minimum score:"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="coachComment" xpath="//div[@class='b_form_element']//textarea[@name='coachcomment']" description="Comments for other coaches textarea"/> + <!-- AssessementForm end --> + <xpath-ui-element name="startBulkAssessment" + xpath="//a[contains(descendant::text(), 'Start bulk assessment')]" + description="Start bulk assessment wizard"/> + <xpath-ui-element name="selectAssessmentCourseNodeInWizard" + xpath="//td[descendant::text()='" + title + "']/../td[2]/a[contains(descendant::text(), 'Select')]" + description="'Select' link of the course node"> + <parameter name="title" description="the title of the test course node"> + <defaultValue value="Bewertung"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="bulkAssessmentValues" + xpath="//div[@class='b_form_element']//textarea" + description="username and score values"/> + <xpath-ui-element name="closeBulkAssessmentWizard" + xpath="//fieldset[./legend[contains(.//text(),'Step 6')]]//a[contains(descendant::text(), 'Close')]" + description="close wizard"/> + + <xpath-ui-element xpath="//div[@class='b_toolbox'][descendant::text()='Assessment tool']//a[descendant::text()='Close']" + name="closeAssessmentTool" description="close the assessment tool"></xpath-ui-element> + + <!-- mmw: beispiel bitte stehen lassen. sonst marions notizbuch entsprechend anpassen --> + <xpath-ui-element xpath="link=Close" name="alsoCloseAssessmentTool" description="plan B of close the assessment tool"></xpath-ui-element> + + </pageset> + + <pageset name="disposed" description="disposed course"> + <xpath-ui-element name="closeAndRestart" xpath="//a[descendant::text()='Close course and restart']" description="Comments for users textarea"/> + </pageset> + + </pageset> + +</ui-map-include> diff --git a/src/test/profile/selenium/ui-map/courseEditor-pageset.xml b/src/test/profile/selenium/ui-map/courseEditor-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..c29da58d8a8b14fed548d94ab1db2e65af70c2d8 --- /dev/null +++ b/src/test/profile/selenium/ui-map/courseEditor-pageset.xml @@ -0,0 +1,928 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="courseEditor" description="A course opened in the editor"> + <pageset name="menu" description="the left hand menu"> + <xpath-ui-element name="link" xpath="//div[@class='b_tree']//a[contains(.//text(),'" + link + "')]" description="a course node link in the courseeditor, containing the linkText" > + <parameter name="link" description="The text of the link"/> + </xpath-ui-element> + </pageset> + <pageset name="content" description="the (center) content area"> + <pageset name="TitleDescription" description="tab title and description"> + <!-- <xpath-ui-element name="tabTitleDescription" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Title and description']" + description="Tab Title and description"/> asa unused --> + <xpath-ui-element name="shortTitle" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Short title']//div[@class='b_form_element']//input[@type='text']" + description="The Short title input field"/> + <!-- <xpath-ui-element name="title" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Title']//div[@class='b_form_element']//input[@type='text']" + description="The Title input field"/> asa unused --> + <xpath-ui-element name="save" + xpath="//div[@class='b_form_element']//button[.//text()='Save']" + description="The Save button"/> + </pageset> + <pageset name="visibility" description="tab visibility"> + <xpath-ui-element name="tabVisibility" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Visibility']" + description="Tab visibility"/> + + <xpath-ui-element name="blockedForLearners" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='coachExclusive']" + description="Checkbox blocked for learners"/> + <xpath-ui-element name="dependingDate" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='dateSwitch']" + description="Checkbox depending on date"/> + <xpath-ui-element name="startDate" + xpath="//div[@class='b_form_subform']//div[@class='b_form_element_wrapper b_clearfix' and .//text()='from']//input" + description="Start date field"/> + <xpath-ui-element name="endDate" + xpath="//div[@class='b_form_subform']//div[@class='b_form_element_wrapper b_clearfix' and .//text()='to']//input" + description="End date field"/> + <xpath-ui-element name="dependingGroup" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='groupSwitch']" + description="Checkbox depending on group"/> + <!-- <xpath-ui-element name="learningGroup" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning groups']//input" + description="form field learning group"/> asa unused --> + + <!-- <xpath-ui-element name="createLearningGroup" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning groups']//a[./span/text()='Create']" + description="create a new learning group"/> asa unused --> + <xpath-ui-element name="selectLearningGroup" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning groups']//a[./span/text()='Select']" + description="select an existing learning group"/> + <!-- <xpath-ui-element name="learningArea" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning areas']//input" + description="form field learning area"/> asa unused --> + <!-- <xpath-ui-element name="createLearningArea" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning areas']//a[./span/text()='Create']" + description="create a new learning area"/> asa unused --> + <!-- <xpath-ui-element name="selectLearningArea" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Only for learning areas']//a[./span/text()='Select']" + description="select an existing learning area"/> asa unused --> + + <xpath-ui-element name="dependingAssessment" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='assessmentSwitch']" + description="Checkbox depending on assessment"/> + <xpath-ui-element name="selectElement" + xpath="//fieldset[./legend/text()='Visibility']//select[@name='nodePassed_SELBOX']" + description="Dropdown select course elment"/> + <!-- <xpath-ui-element name="valueCheck" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='assessmentTypeSwitch' and @value='score']" + description="Radio Button value check with value 'passed'"/> asa unused --> + <!-- <xpath-ui-element name="passedCheck" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='assessmentTypeSwitch' and @value='passed']" + description="Radio Button value check with value 'score'"/> asa unused --> + <!-- <xpath-ui-element name="passingScore" + xpath="//fieldset[./legend/text()='Visibility']//div[./div/div/div/label/text()='Passing score']//input" + description="Field passing score"/> asa unused --> + <!-- <xpath-ui-element name="applyRulesForOwners" + xpath="//fieldset[./legend/text()='Visibility']//input[@name='applyRulesForCoach']" + description="Checkbox apply rules also for owners and tutors"/> asa unused --> + <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Visibility']//button[@value='Save']" + description="save button tab visibility"/> + <xpath-ui-element name="saveInfo" + xpath="//fieldset[./legend/text()='Information if visible and no access']//button[@value='Save']" + description="save button info field"/> + + </pageset> + <pageset name="access" description="tab access"> + <!-- TODO sr/ki add links--> + <xpath-ui-element name="tabAccess" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Access']" + description="Tab access"/> + <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Access']//button[@value='Save']" + description="general save button tab visibility"/> + <xpath-ui-element name="blockedForLearnersReadAndWrite" + xpath="//fieldset[./legend/text()='Read and write (up/download)']//input[@name='coachExclusive']" + description="Checkbox blocked for learners in field Read and write (up and download)"/> + <xpath-ui-element name="saveReadAndWrite" + xpath="//fieldset[./legend/text()='Read and write (up/download)']//button[@value='Save']" + description="save button tab access read and write"/> + <xpath-ui-element name="blockedForLearnersReadOnly" + xpath="//fieldset[./legend/text()='Read only (download)']//input[@name='coachExclusive']" + description="Checkbox blocked for learners in field Read only (download)"/> + + <xpath-ui-element name="blockedForLearners" + xpath="//fieldset[./legend/text()='" + fieldsetLegend + "']//input[@name='coachExclusive']" + description="Checkbox blocked for learners in field Read only (download)"> + <parameter name="fieldsetLegend" description="fieldset legend text"/> + </xpath-ui-element> + <xpath-ui-element name="saveAccess" xpath="//fieldset[./legend/text()='" + fieldsetLegend + "']//button[@value='Save']" description="save access"> + <parameter name="fieldsetLegend" description="save access for the specified fieldset"></parameter> + </xpath-ui-element> + + <xpath-ui-element name="saveReadOnly" + xpath="//fieldset[./legend/text()='Read only (download)']//button[@value='Save']" + description="save button tab access read only"/> + + <xpath-ui-element name="dependingDate" + xpath="//fieldset[./legend/text()='Access']//input[@name='dateSwitch']" + description="Checkbox depending on date"/> + <xpath-ui-element name="startDate" + xpath="//div[@class='b_form_subform']//div[@class='b_form_element_wrapper b_clearfix' and .//text()='from']//input" + description="Start date field"/> + <xpath-ui-element name="endDate" + xpath="//div[@class='b_form_subform']//div[@class='b_form_element_wrapper b_clearfix' and .//text()='to']//input" + description="End date field"/> + <xpath-ui-element name="dependingGroup" + xpath="//fieldset[./legend/text()='Access']//input[@name='groupSwitch']" + description="Checkbox depending on group"/> + <!-- <xpath-ui-element name="learningGroup" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning groups']//input" + description="form field learning group"/> asa unused --> + + <!-- <xpath-ui-element name="createLearningGroup" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning groups']//a[./span/text()='Create']" + description="create a new learning group"/> asa unused --> + <xpath-ui-element name="selectLearningGroup" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning groups']//a[./span/text()='Select']" + description="select an existing learning group"/> + <!-- <xpath-ui-element name="learningArea" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning areas']//input" + description="form field learning area"/> asa unused --> + <!-- <xpath-ui-element name="createLearningArea" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning areas']//a[./span/text()='Create']" + description="create a new learning area"/> asa unused --> + <!-- <xpath-ui-element name="selectLearningArea" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Only for learning areas']//a[./span/text()='Select']" + description="select an existing learning area"/> asa unused --> + + <!-- <xpath-ui-element name="dependingAssessment" + xpath="//fieldset[./legend/text()='Access']//input[@name='assessmentSwitch']" + description="Checkbox depending on assessment"/> asa unused --> + <!-- <xpath-ui-element name="selectElement" + xpath="//fieldset[./legend/text()='Access']//select[@name='nodePassed_SELBOX']" + description="Dropdown select course elment"/> asa unused --> + <!-- <xpath-ui-element name="valueCheck" + xpath="//fieldset[./legend/text()='Access']//input[@name='assessmentTypeSwitch' and @value='score']" + description="Radio Button value check with value 'passed'"/> asa unused --> + <!-- <xpath-ui-element name="passedCheck" + xpath="//fieldset[./legend/text()='Access']//input[@name='assessmentTypeSwitch' and @value='passed']" + description="Radio Button value check with value 'score'"/> asa unused --> + <!-- <xpath-ui-element name="passingScore" + xpath="//fieldset[./legend/text()='Access']//div[./div/div/div/label/text()='Passing score']//input" + description="Field passing score"/> asa unused --> + <!-- <xpath-ui-element name="applyRulesForOwners" + xpath="//fieldset[./legend/text()='Access']//input[@name='applyRulesForCoach']" + description="Checkbox apply rules also for owners and tutors"/> asa unused --> + + + </pageset> + <pageset name="visibilityOrAccess" description="common paths for visibility or access"> + <xpath-ui-element name="displayExpertMode" xpath="//a[.//text()='Display expert mode']" description="display expert mode button"/> + <xpath-ui-element name="displaySimpleMode" xpath="//a[.//text()='Display simple mode']" description="display simple mode button"/> + <xpath-ui-element name="saveVisibilityExpertRule" xpath="//fieldset[./legend/text()='Visibility']//button[@value='Save']" description="save visibility expert rule"/> + <xpath-ui-element name="saveAccessExpertRule" xpath="//fieldset[./legend/text()='Access']//button[@value='Save']" description="save accesss expert rule"/> + </pageset> + <pageset name="bbStructure" description="configuration of structure"> + <xpath-ui-element name="scoreTab" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Score']" + description="score tab link"/> + <xpath-ui-element name="minimumScore" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Minimum score']//div[@class='b_form_element']//input[@type='text']" + description="minimum score input form element"/> + </pageset> + <pageset name="bbSinglePage" description="configuration of single page"> + <!-- TODO sr/ki add links--> + <xpath-ui-element name="tabPageContent" + xpath="//div[preceding-sibling::h4[contains(@class,'o_sp_icon')]]//div[@class='b_tabbedpane_tabs']//a[.//text()='Page content']" + description="Tab page content (single page)"/> + <xpath-ui-element name="replacePage" + xpath="//div[contains(@class, 'b_tabbedpane_content_inner')]//a[contains(@href, 'command.changefile')]" + description="Replace HTML-page"/> + <!-- <xpath-ui-element name="openPageInEditor" + xpath="//div[contains(@class, 'b_tabbedpane_content_inner')]//a[contains(@href, 'command.edit')]" + description="Open page in editor"/> asa unused --> + <xpath-ui-element name="previewSinglePage" + xpath="//div[contains(@class, 'b_tabbedpane_content_inner')]//a[contains(@href, 'command.preview')]" + description="Show preview of attached single page"/> + <xpath-ui-element name="selectOrCreatePage" + xpath="//div[contains(@class, 'b_tabbedpane_content_inner')]//a[contains(@href, 'command.choosecreatefile')]" + description="Select or create page"/> + <xpath-ui-element name="saveAndClose" xpath="//a[.//text()='Save and close']" description="Save and close button"/> + + </pageset> + <pageset name="bbExternalPage" description="configuration of external page"> + <!-- TODO sr/ki add links--> + <!-- <xpath-ui-element name="tabPageContent" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Page content']" + description="Tab page content (external page)"/> asa unused --> + </pageset> + <pageset name="bbCP" description="configuration of CP"> + <xpath-ui-element name="tabLearningContentCP" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Learning content']" + description="Tab learning content (CP)"/> + <xpath-ui-element name="selectCreateImportCP" + xpath="//fieldset[./legend/text()='Select CP learning content']//a[@class='b_button b_small']" + description="button select, create or import CP"/> + </pageset> + <pageset name="bbForum" description="configuration of SCORM"> + <!-- TODO sr/ki add links--> + <!-- <xpath-ui-element name="tabLearningContentScorm" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Learning content']" + description="Tab learning content (Scorm)"/> asa unused --> + </pageset> + <pageset name="bbWiki" description="configuration of wiki "> + <xpath-ui-element name="tabWikiLearningContent" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Wiki learning content']" + description="Tab wiki learning content"/> + <xpath-ui-element name="chooseWiki" + xpath="//fieldset[./legend/text()='Select Wiki']//a[@class='b_button b_small']" + description="button choose wiki"/> + <!-- <xpath-ui-element name="replaceWiki" + xpath="//fieldset[./legend/text()='Select Wiki']//a[.//text()='Replace Wiki ']" + description="button replace wiki"/> asa unused --> + + <!-- TODO se evtl auslagern da dieser search screen auch bei anderen bausteinen (test, fragebogen) kommt --> + + + </pageset> + <pageset name="bbFileDialog" description="configuration of file dialog"> + <!-- TODO sr/ki add links--> + <!-- <xpath-ui-element name="tabForumStorage" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Forum/storage configuration']" + description="Tab Forum/storage configuration"/> asa unused --> + </pageset> + <pageset name="bbFolder" description="configuration of folder"> + <!-- TODO sr/ki add links--> + <xpath-ui-element name="tabFolderConfiguration" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Folder configuration']" + description="Tab folder configuration)"/> + </pageset> + <pageset name="bbAssessment" description="configuration of assessment"> + <!-- TODO sr/ki add links--> + <xpath-ui-element name="tabAssessment" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Assessment']" + description="Tab assessment"/> + </pageset> + <pageset name="bbTask" description="configuration of task"> + <!-- TODO sr/ki add links--> + <!-- <xpath-ui-element name="tabSubElements" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Sub-elements']" + description="Tab sub-elements"/> asa unused --> + <!-- <xpath-ui-element name="tabAssignment" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Assignment']" + description="Tab assignment"/> asa unused --> + <!-- <xpath-ui-element name="tabHandingIn" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Handing in']" + description="Tab handing in"/> asa unused --> + <!-- <xpath-ui-element name="tabAssessment" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Assessment']" + description="Tab assessment"/> asa unused --> + <!-- <xpath-ui-element name="tabSampleSolution" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Sample solution']" + description="Tab sample solution"/> asa unused --> + </pageset> + <pageset name="bbTest" description="configuration of test"> + <xpath-ui-element name="tabTestConfiguration" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Test configuration']" + description="Tab test configuration"/> + <xpath-ui-element name="chooseFile" + xpath="//fieldset[./legend/text()='Test']//a[.//text()='Choose, create or import file']" + description="Button choose file"/> + <pageset name="layoutParameters" description="section layout parameters"> + <xpath-ui-element name="limitNumOfAttempts" xpath="//div[@class='b_form_element']//input[@name='limitAttempts']" description="limit number of attempts checkbox"/> + <xpath-ui-element name="showMenuNavigation" xpath="//div[@class='b_form_element']//input[@name='qti_displayMenu']" description="showMenuNavigation checkbox"/> + <xpath-ui-element name="allowMenuNavigation" xpath="//div[@class='b_form_element']//input[@name='qti_enableMenu']" description="allowMenuNavigation checkbox"/> + <xpath-ui-element name="allowCancel" xpath="//div[@class='b_form_element']//input[@name='qti_enableCancel']" description="allowCancel checkbox"/> + <xpath-ui-element name="allowSuspend" xpath="//div[@class='b_form_element']//input[@name='qti_enableSuspend']" description="allowSuspend checkbox"/> + <xpath-ui-element name="displayResultsOnTestHomepage" xpath="//div[@class='b_form_element']//input[@name='qti_enableResultsOnHomePage']" description="displayResultsOnTestHomepage checkbox"/> + + <!-- <xpath-ui-element name="allowMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='y']" + description="Radio Button (Yes) allow menu navigation"/> + <xpath-ui-element name="allowMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='n']" + description="Radio Button (No) allow menu navigation"/> + <xpath-ui-element name="showMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='y']" + description="Radio Button (Yes) show menu navigation"/> + <xpath-ui-element name="showMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='n']" + description="Radio Button (No) show menu navigation"/> + <xpath-ui-element name="clusteringOfQuestions" + xpath="//select[@name='qti_form_sequence']" + description="Dropdown clustering of questions"/> + <xpath-ui-element name="showNrOfQuestionsYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='y']" + description="Radio Button (Yes) show number of questions"/> + <xpath-ui-element name="showNrOfQuestionsNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='n']" + description="Radio Button (No) show number of questions"/> + <xpath-ui-element name="showQuestionTitleYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='y']" + description="Radio Button (Yes) show question title"/> + <xpath-ui-element name="showQuestionTitleNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='n']" + description="Radio Button (No) show question title"/> + <xpath-ui-element name="allowCancelYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='y']" + description="Radio Button (Yes) allow to cancel"/> + <xpath-ui-element name="allowCancelNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='n']" + description="Radio Button (No) allow to cancel"/> + <xpath-ui-element name="allowSuspendYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='y']" + description="Radio Button (Yes) allow to suspend"/> + <xpath-ui-element name="allowSuspendNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='n']" + description="Radio Button (No) allow to suspend"/> + <xpath-ui-element name="maximumNrOfApproach" + xpath="//select[@name='qti_form_attempts']" + description="Dropdown max number of approaches"/> + <xpath-ui-element name="showScoreInTestYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableScoreProgress' and @value='y']" + description="Radio Button (Yes) show score in test"/> + <xpath-ui-element name="showScoreInTestNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableScoreProgress' and @value='n']" + description="Radio Button (No) show score in test"/> + <xpath-ui-element name="displayScoreOnTestHomepageYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_scoreInfo' and @value='y']" + description="Radio Button (Yes) display score on test homepage"/> + <xpath-ui-element name="displayScoreOnTestHomepageNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_scoreInfo' and @value='n']" + description="Radio Button (No) display score on test homepage"/> + <xpath-ui-element name="showResultsAfterTestSubmittedYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnFinish' and @value='y']" + description="Radio Button (Yes) display results after test has been submitted"/> + <xpath-ui-element name="showResultsAfterTestSubmittedNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnFinish' and @value='n']" + description="Radio Button (No) display results after test has been submitted"/> + <xpath-ui-element name="displayresultsOnTestHomepageYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnHomePage' and @value='y']" + description="Radio Button (Yes) display results on test homepage"/> + <xpath-ui-element name="displayresultsOnTestHomepageNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnHomePage' and @value='n']" + description="Radio Button (No) display results on test homepage"/> + <xpath-ui-element name="displayDependingDateYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_showresult' and @value='y']" + description="Radio Button (Yes) display depending on date"/> + <xpath-ui-element name="displayDependingDateNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_showresult' and @value='n']" + description="Radio Button (No) display depending on date"/> + <xpath-ui-element name="overviewResults" + xpath="//select[@name='qti_form_summary']" + description="Dropdown overview results"/> + <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@value='Save']" + description="save button layout parameters"/> --> + <!-- <xpath-ui-element name="startDate" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti.form.date.start']" + description="Field start date"/> asa unused --> + <!-- <xpath-ui-element name="endDate" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti.form.date.end']" + description="Field end date"/> asa unused --> + </pageset> + </pageset> + <pageset name="bbSelfTest" description="configuration of self-test"> + <xpath-ui-element name="tabSelfTestConfiguration" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Self-test configuration']" + description="Tab self-test configuration"/> + <xpath-ui-element name="chooseFile" + xpath="//fieldset[./legend/text()='Self-test']//a[.//text()='Choose, create or import file']" + description="Button choose file"/> + <!-- <pageset name="layoutParameters" description="section layout parameters"> + <xpath-ui-element name="allowMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='y']" + description="Radio Button (Yes) allow menu navigation"/> + <xpath-ui-element name="allowMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='n']" + description="Radio Button (No) allow menu navigation"/> + <xpath-ui-element name="showMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='y']" + description="Radio Button (Yes) show menu navigation"/> + <xpath-ui-element name="showMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='n']" + description="Radio Button (No) show menu navigation"/> + <xpath-ui-element name="clusteringOfQuestions" + xpath="//select[@name='qti_form_sequence']" + description="Dropdown clustering of questions"/> + <xpath-ui-element name="showNrOfQuestionsYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='y']" + description="Radio Button (Yes) show number of questions"/> + <xpath-ui-element name="showNrOfQuestionsNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='n']" + description="Radio Button (No) show number of questions"/> + <xpath-ui-element name="showQuestionTitleYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='y']" + description="Radio Button (Yes) show question title"/> + <xpath-ui-element name="showQuestionTitleNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='n']" + description="Radio Button (No) show question title"/> + <xpath-ui-element name="allowCancelYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='y']" + description="Radio Button (Yes) allow to cancel"/> + <xpath-ui-element name="allowCancelNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='n']" + description="Radio Button (No) allow to cancel"/> + <xpath-ui-element name="allowSuspendYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='y']" + description="Radio Button (Yes) allow to suspend"/> + <xpath-ui-element name="allowSuspendNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='n']" + description="Radio Button (No) allow to suspend"/> + <xpath-ui-element name="showScoreInTestYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableScoreProgress' and @value='y']" + description="Radio Button (Yes) show score in test"/> + <xpath-ui-element name="showScoreInTestNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableScoreProgress' and @value='n']" + description="Radio Button (No) show score in test"/> + <xpath-ui-element name="displayScoreOnTestHomepageYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_scoreInfo' and @value='y']" + description="Radio Button (Yes) display score on test homepage"/> + <xpath-ui-element name="displayScoreOnTestHomepageNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_scoreInfo' and @value='n']" + description="Radio Button (No) display score on test homepage"/> + <xpath-ui-element name="showResultsAfterTestSubmittedYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnFinish' and @value='y']" + description="Radio Button (Yes) display results after test has been submitted"/> + <xpath-ui-element name="showResultsAfterTestSubmittedNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnFinish' and @value='n']" + description="Radio Button (No) display results after test has been submitted"/> + <xpath-ui-element name="displayresultsOnTestHomepageYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnHomePage' and @value='y']" + description="Radio Button (Yes) display results on test homepage"/> + <xpath-ui-element name="displayresultsOnTestHomepageNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableResultsOnHomePage' and @value='n']" + description="Radio Button (No) display results on test homepage"/> + <xpath-ui-element name="displayDependingDateYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_showresult' and @value='y']" + description="Radio Button (Yes) display depending on date"/> + <xpath-ui-element name="displayDependingDateNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_showresult' and @value='n']" + description="Radio Button (No) display depending on date"/> + <xpath-ui-element name="overviewResults" + xpath="//select[@name='qti_form_summary']" + description="Dropdown overview results"/> + <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@value='Save']" + description="save button layout parameters"/> + <xpath-ui-element name="startDate" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti.form.date.start']" + description="Field start date"/> + <xpath-ui-element name="endDate" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti.form.date.end']" + description="Field end date"/> + </pageset>--> + </pageset> + <pageset name="bbQuestionnaire" description="configuration of questionnaire"> + <xpath-ui-element name="tabQuestionnaireConfiguration" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Questionnaire configuration']" + description="Tab questionnaire configuration"/> + <xpath-ui-element name="chooseFile" + xpath="//fieldset[./legend/text()='Questionnaire']//a[@class='b_button b_small']" + description="Button choose file"/> + <!-- <pageset name="layoutParameters" description="section layout parameters"> + <xpath-ui-element name="allowMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='y']" + description="Radio Button (Yes) allow menu navigation"/> + <xpath-ui-element name="allowMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableMenu' and @value='n']" + description="Radio Button (No) allow menu navigation"/> + <xpath-ui-element name="showMenuNavigationYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='y']" + description="Radio Button (Yes) show menu navigation"/> + <xpath-ui-element name="showMenuNavigationNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayMenu' and @value='n']" + description="Radio Button (No) show menu navigation"/> + <xpath-ui-element name="clusteringOfQuestions" + xpath="//select[@name='qti_form_sequence']" + description="Dropdown clustering of questions"/> + <xpath-ui-element name="showNrOfQuestionsYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='y']" + description="Radio Button (Yes) show number of questions"/> + <xpath-ui-element name="showNrOfQuestionsNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableQuestionProgress' and @value='n']" + description="Radio Button (No) show number of questions"/> + <xpath-ui-element name="showQuestionTitleYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='y']" + description="Radio Button (Yes) show question title"/> + <xpath-ui-element name="showQuestionTitleNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_displayQuestionTitle' and @value='n']" + description="Radio Button (No) show question title"/> + <xpath-ui-element name="allowCancelYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='y']" + description="Radio Button (Yes) allow to cancel"/> + <xpath-ui-element name="allowCancelNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableCancel' and @value='n']" + description="Radio Button (No) allow to cancel"/> + <xpath-ui-element name="allowSuspendYes" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='y']" + description="Radio Button (Yes) allow to suspend"/> + <xpath-ui-element name="allowSuspendNo" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@name='qti_enableSuspend' and @value='n']" + description="Radio Button (No) allow to suspend"/> + <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Layout parameters']//input[@value='Save']" + description="save button layout parameters"/> + </pageset> --> + </pageset> + <pageset name="bbEnrolment" description="configuration of enrolment"> + <xpath-ui-element name="tabConfiguration" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[@class='b_tabbedpane_tabs']//a[.//text()='Configuration']" + description="Tab configuration"/> + <!-- <xpath-ui-element name="learningGroup" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning groups']//input" + description="form field learning group"/> asa unused --> + <!-- <xpath-ui-element name="learningArea" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning areas']//input" + description="form field learning area"/> asa unused --> + + <!-- <xpath-ui-element name="createLearningGroup" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning groups']//a[./span/text()='Create']" + description="create a new learning group"/> asa unused --> + <xpath-ui-element name="selectLearningGroup" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning groups']//a[./span/text()='Select']" + description="select an existing learning group"/> + <!-- <xpath-ui-element name="createLearningArea" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning areas']//a[./span/text()='Create']" + description="create a new learning area"/> asa unused --> + <xpath-ui-element name="selectLearningArea" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//div[./div/div/div/label/text()='Learning areas']//a[./span/text()='Select']" + description="select an existing learning area"/> + <!-- <xpath-ui-element name="enableCancelEnroll" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//input[@name='enableCancelEnroll']" + description="enable Cancel Enroll"/> asa unused --> + <xpath-ui-element name="save" + xpath="//div[contains(./h4/@class, 'o_en_icon')]//button[@value='Save']" + description="save button tab configuration"/> + + <pageset name="selectLearningGroupDialog" + description="the select learning group dialog"> + <!-- <xpath-ui-element name="create" + xpath="//div[@class='b_window']//a[.//text()='Create']" + description="create button - create a new learning group"/> asa unused --> + <xpath-ui-element name="checkGroup" + xpath="//div[@class='b_window']//input[@class='b_checkbox' and @value='" + nameOfGroup + "']" + description="check a learning group"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + <xpath-ui-element name="apply" + xpath="//div[@class='b_window']//button[.//text()='Apply']" + description="create button - create a new learning group"/> + <!-- <xpath-ui-element name="cancel" + xpath="//div[@class='b_window']//button[.//text()='Cancel']" + description="create button - create a new learning group"/> asa unused --> + </pageset> + + <pageset name="createLearningGroupDialog" + description="the create learning group dialog"> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@id='fe_bgName']" + name="groupName" description="form field group name"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//textarea[@name='fe_bgWkDescription']" + name="groupDescription" description="form field group description"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@id='fe_bgMax']" + name="maxParticipants" description="form field max participants"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@name='enableWaitinglist']" + name="waitingList" description="form field waiting list"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@name='enableAutoCloseRanks']" + name="moveUpAutomatically" description="form field move up automatically"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@value='Save']" + name="save" description="save button description"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='groupForm']//input[@value='Cancel']" + name="cancel" description="cancel button description"/> asa unused --> + </pageset> + + <pageset name="createLearningAreaDialog" + description="the create learning area dialog"> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='areaForm']//input[@id='name']" + name="name" description="form field learning area name"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='areaForm']//textarea[@name='description']" + name="description" description="form field description"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='areaForm']//input[@value='Save']" + name="save" description="save button description"/> asa unused --> + <!-- <xpath-ui-element + xpath="//div[@class='b_window']//form[@name='areaForm']//input[@value='Cancel']" + name="cancel" description="cancel button description"/> asa unused --> + </pageset> + + </pageset> + <pageset name="bbContactForm" description="configuration of contact form"> + <!-- TODO sr/ki add links--> + <!-- <xpath-ui-element name="tabRecipient" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Recipient']" + description="Tab recipient"/> asa unused --> + </pageset> + <!-- new for 6.3--> + <pageset name="bbBlog" description="configuration of blog"> + <xpath-ui-element name="tabBlogLearningContent" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Blog learning content']" + description="Tab blog learning content"/> + <xpath-ui-element name="selectCreateImportBlog" + xpath="//fieldset[./legend/text()='Select blog']//a[@class='b_button b_small']" + description="button select, create or import blog"/> + <xpath-ui-element name="editBlog" + xpath="//fieldset[./legend/text()='Select blog']//a[@class='b_button b_small' and .//text()='Edit']" + description="button edit blog"/> + <xpath-ui-element name="replaceBlog" + xpath="//fieldset[./legend/text()='Select blog']//a[@class='b_button b_small' and .//text()='Replace blog']" + description="button replace blog"/> + <xpath-ui-element name="create" xpath="//a[.//text()='Create']" description="create blog button"/> + </pageset> + <pageset name="bbPodcast" description="configuration of podcast"> + <xpath-ui-element name="tabPodcastLearningContent" + xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Podcast learning content']" + description="Tab podcast content"/> + <xpath-ui-element name="selectCreateImportPodcast" + xpath="//fieldset[./legend[contains(.//text(),'Select')]]//a[@class='b_button b_small']" + description="button select, create or import podcast"/> + <xpath-ui-element name="editPodcast" + xpath="//fieldset[./legend/text()='Select podcast']//a[@class='b_button b_small'][descendant::text()='Edit']" + description="button edit podcast"/> + <xpath-ui-element name="replacePodcast" + xpath="//fieldset[./legend/text()='Select Podcast']//a[.//text()='Replace Podcast']" + description="button replace podcast"/> + <xpath-ui-element name="create" xpath="//a[.//text()='Create']" description="create podcast button"/> + </pageset> + <pageset name="bbTopicAssignment" description="topic assignment links"> + <xpath-ui-element name="tabConfig" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Configuration']" description="configutation tab"/> + <xpath-ui-element name="topicsPerParticipant" xpath="//input[@name='form.options.number.of.topics.per.participant']" description="Limit topics per participant: yes or no"/> + <xpath-ui-element name="howManyTopicsPerParticipant" xpath="//div[@class='b_form_element_wrapper b_clearfix']//div[@class='b_form_element']//input[@type='text']" description="if limited topics per participant, how many?"/> + <xpath-ui-element name="topicSelectionAccept" xpath="//input[@name='form.options.selection.accept']" description="topic authors have to accept participants"/> + <xpath-ui-element name="onlyOneTopicAllowed" xpath="//input[@name='form.options.auto.sign.out']" description="only one topic allowed"/> + <xpath-ui-element name="saveConfig" xpath="//fieldset[./legend='Configuration']//button[@value='Save']" description="save configuration - cannot use generic button"></xpath-ui-element> + <xpath-ui-element name="tabPersons" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Persons in charge']" description="tab persons in charge"/> + </pageset> + <pageset name="lti" description="lti xpaths"> + <xpath-ui-element name="tabPageContent" + xpath="//div[preceding-sibling::h4[contains(@class,'o_lti_icon')]]//div[@class='b_tabbedpane_tabs']//a[.//text()='Page content']" + description="Tab page content (single page)"/> + </pageset> + <pageset name="assessmentElemConfig" description="configuration of assessment course element"> + <xpath-ui-element name="scoreGranted" + xpath="//input[@name='form.score']" + description="Score granted - Yes/No"/> + <xpath-ui-element name="minimumScore" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Minimum score']//div[@class='b_form_element']//input[@type='text']" + description="set minimum score"/> + <xpath-ui-element name="maximumScore" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Maximum score']//div[@class='b_form_element']//input[@type='text']" + description="set maximum score"/> + <xpath-ui-element name="passedTypeAuto" + xpath="//input[@name='form.passed.type' and @value='true']" + description="Type of display - Automatic"/> + <!-- <xpath-ui-element name="passedTypeManual" + xpath="//input[@name='form.passed.type' and @value='false']" + description="Type of display - Manual by tutor"/> asa unused --> + <xpath-ui-element name="passedCutValue" + xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Passed cut value']//div[@class='b_form_element']//input[@type='text']" + description="set Passed cut value"/> + <xpath-ui-element name="passedCutValueErr" + xpath="//div[@class='b_form_element_wrapper b_form_error b_clearfix'][descendant::text()='Passed cut value']//div[@class='b_form_element']//input[@type='text']" + description="set Passed cut value"/> + </pageset> + <xpath-ui-element name="undeleteCourseElement" xpath="//a[.//text()='Restore course element']" description="Restore course element button"/> + </pageset> + + <pageset name="toolbox" description="the toolbox area to the right"> + <pageset name="editorTools" description="the editor tools toolbox"> + <link-ui-element name="storageFolder" link="Storage folder" + description="The Storage folder link"/> + <link-ui-element name="coursePreview" link="Course preview" + description="The Course previewlink"/> + <link-ui-element name="publish" link="Publish" description="The Publish link"/> + <link-ui-element name="closeEditor" link="Close editor" + description="The close editor link"/> + </pageset> + <pageset name="insertCourseElements" description="the insert course elements toolbox"> + <xpath-ui-element name="insertStructure" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Structure']" + description="Insert Structure course element"/> + <xpath-ui-element name="insertSinglePage" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Single page']" + description="Insert single page course element"/> + <xpath-ui-element name="insertExternalPage" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='External page']" + description="Insert external page course element"/> + <xpath-ui-element name="insertCP" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='CP learning content']" + description="Insert cp course element"/> + <xpath-ui-element name="insertSCORM" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='SCORM learning content']" + description="Insert scorm course element"/> + <xpath-ui-element name="insertForum" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Forum']" + description="Insert forum course element"/> + <xpath-ui-element name="insertWiki" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Wiki']" + description="Insert wiki course element"/> + <xpath-ui-element name="insertFileDialog" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='File dialog']" + description="Insert file dialog course element"/> + <xpath-ui-element name="insertFolder" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Folder']" + description="Insert folder course element"/> + <xpath-ui-element name="insertAssessment" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Assessment']" + description="Insert assessment course element"/> + <xpath-ui-element name="insertTask" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Task']" + description="Insert task course element"/> + <xpath-ui-element name="insertTest" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Test']" + description="Insert test course element"/> + <xpath-ui-element name="insertSelfTest" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Self-test']" + description="Insert self-test course element"/> + <xpath-ui-element name="insertQuestionnaire" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Questionnaire']" + description="Insert questionnaire course element"/> + <xpath-ui-element name="insertEnrolment" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Enrolment']" + description="Insert enrolment course element"/> + <xpath-ui-element name="insertContactForm" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='E-mail']" + description="Insert contact form course element"/> + <!-- new elements for 6.3--> + <xpath-ui-element name="insertBlog" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Blog']" + description="Insert contact form course element"/> + <xpath-ui-element name="insertPodcast" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Podcast']" + description="Insert contact form course element"/> + <xpath-ui-element name="insertTopicAssignment" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Topic assignment']" + description="Insert contact form course element"/> + <xpath-ui-element name="insertCalendar" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Calendar']" + description="Insert contact form course element"/> + <xpath-ui-element name="insertLTIPage" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='LTI page']" + description="Insert LTI page course element"/> + <xpath-ui-element name="insertInfoMessagePage" + xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[@class='o_infomsg_icon']" + description="Insert info message course element"/> + + <xpath-ui-element name="insertAsRootsFirstChild" + xpath="//div[@class='b_selectiontree_content']//input[@class='b_radio']" + description="Choose first child of root"/> + <xpath-ui-element name="insertAsRootsLastChild" + xpath="//div[@class='b_selectiontree_item'][last()]//div[@class='b_selectiontree_content']//input[@class='b_radio']" + description="Choose last child of root"/> + <xpath-ui-element name="insertAsElementsFirstChild" + xpath="//div[@class='b_selectiontree_item' and .//text()='" + title +"']/following-sibling::div[1]//input[@class='b_radio']" + description="Choose first child of the element with the given title"> + <parameter name="title" description="the title of the course element"/> + </xpath-ui-element> + <xpath-ui-element name="insertAsElementsFollowingSibling" + xpath="//div[@class='b_selectiontree_item' and .//text()='" + title +"']/following-sibling::div[2]//input[@class='b_radio']" + description="Choose first child of the element with the given title"> + <parameter name="title" description="the title of the course element"/> + </xpath-ui-element> + + <xpath-ui-element name="clickInsertCourseElement" + xpath="//button[.//text()='Insert course element']" + description="Click Insert course element"/> + + <!-- <xpath-ui-element name="cancel" xpath="//button[.//text()='Cancel']" + description="Cancel Insert course element"/> asa unused --> + </pageset> + <pageset name="modifyTools" description="the modify course elements toolbox"> + <link-ui-element name="delete" link="Delete" description="The Delete link"/> + <link-ui-element name="move" link="Move " description="The Move link"/> + <link-ui-element name="copy" link="Copy" description="The Copy link"/> + </pageset> + <!--TODO se xpaths stimmen nicht <pageset name="modifyTools" description="the modify course elements toolbox"> + <xpath-ui-element name="delete" xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Delete']" description="Delete course element"/> + <xpath-ui-element name="move" xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Move']" description="Move course element"/> + <xpath-ui-element name="copy" xpath="//div[@class='b_toolbox'][2]//div[@class='b_toolbox_content']//a[.//text()='Copy']" description="Copy course element"/> + </pageset>--> + </pageset> + <pageset name="preview" description="the course preview wizard"> + <link-ui-element name="closePreview" link="Close preview" description="The Close Preview link"/> + <xpath-ui-element name="selectRole" xpath="//input[@value='" + role + "']" description="select role"> + <parameter name="role" description="the title of the course element"/> + </xpath-ui-element> + <!-- TODO se: better xpath --> + <xpath-ui-element name="showCoursePreview" xpath="//button[@value='Show course preview']" + description="the show course preview button"/> + </pageset> + <pageset name="publishDialog" description="the publish dialog"> + <pageset name="howToPublish" description="The first page 'How to publish'"> + <xpath-ui-element name="firstTreeCheckbox" xpath="//input[@name='seltree']" + description="the first element of the tree - Checkbox"/> + </pageset> + <xpath-ui-element name="selectall" xpath="//a[descendant::text()='Select all']" description="The Select all Link"/> + <link-ui-element name="next" link="Next" description="The Next button"/> + <link-ui-element name="back" link="Back" description="The Back button"/> + <link-ui-element name="finish" link="Finish" description="The Finish button"/> + <link-ui-element name="cancel" link="Cancel" description="The Cancel button"/> + + <xpath-ui-element name="courseAccessDropDown" xpath="//select[contains(@name,'access') and contains(@name,'SELBOX')]" + description="The Course Access Drop-Down"/> + + + </pageset> + <pageset name="commons" description="common ui elements of course Editor"> + <pageset name="chooseLr" description="overlay choose learning resources search form"> + <!-- <xpath-ui-element name="allEntries" + xpath="//div[h3/text()='Search for referenceable learning resources']//a[.//text()='All entries']" + description="link all entries"/> asa unused --> + <xpath-ui-element name="myEntries" + xpath="//div[h3/text()='Search for referenceable learning resources']//a[.//text()='My entries']" + description="link my entries"/> + <xpath-ui-element name="search" + xpath="//div[h3/text()='Search for referenceable learning resources']//a[.//text()='Search']" + description="Search link"/> + <!-- <xpath-ui-element name="fieldTitle" + xpath="//form[@name='searchform']//input[@name='cif_displayname']" + description="field title"/> asa unused --> + <!-- <xpath-ui-element name="fieldAuthor" + xpath="//form[@name='searchform']//input[@name='cif_author']" + description="field author"/> asa unused --> + <!-- <xpath-ui-element name="fieldDescription" + xpath="//form[@name='searchform']//input[@name='cif_description']" + description="field description"/> asa unused --> + <!-- <xpath-ui-element name="fieldID" + xpath="//form[@name='searchform']//input[@name='cif_id']" description="field ID"/> asa unused --> + <!-- <xpath-ui-element name="searchButton" + xpath="//form[@name='searchform']//input[@value='Search']" + description="search button"/> asa unused --> + <xpath-ui-element name="chooseWiki" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + nameOfWiki +"']//a[contains(text(), 'Choose Wiki')]" + description="link choose wiki after wiki entry"> + <parameter name="nameOfWiki" description="the name of the wiki"/> + </xpath-ui-element> + <xpath-ui-element name="chooseTest" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + nameOfTest +"']//a[contains(text(), 'Choose test')]" + description="link choose test or self test after test entry"> + <parameter name="nameOfTest" description="the name of the test"/> + </xpath-ui-element> + <xpath-ui-element name="chooseQuestionnaire" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + nameOfQuestionnaire +"']//a[contains(text(), 'Choose questionnaire')]" + description="link choose questionnaire after questionnaire entry"> + <parameter name="nameOfQuestionnaire" + description="the name of the questionnaire"/> + </xpath-ui-element> + <xpath-ui-element name="chooseCP" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + name +"']//a[contains(text(), 'Choose CP learning content')]" + description="link choose CP"> + <parameter name="name" description="the name of the CP"/> + </xpath-ui-element> + <!-- new for 6.3--> + <xpath-ui-element name="chooseBlog" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + nameOfBlog +"']//a[contains(text(), 'Select blog')]" + description="link choose blog after blog entry"> + <parameter name="nameOfBlog" description="the name of the blog"/> + </xpath-ui-element> + <xpath-ui-element name="choosePodcast" + xpath="//div[div//a[@class='b_table_download']]//table//tr[.//a/text()='" + nameOfPodcast +"']//a[contains(text(), 'Select Podcast')]" + description="link choose podcast after podcast entry"> + <parameter name="nameOfPodcast" description="the name of the podcast"/> + </xpath-ui-element> + </pageset> + <pageset name="informationHTMLPage" description="section information (HTML page) in test, questionnaire selftest and structure tabs"> + <!-- <xpath-ui-element name="selectCreatePage" + xpath="//fieldset[./legend/text()='Information (HTML page)']//a[.//text()='Select or create page']" + description="Button select or create page"/> asa unused --> + <!-- <xpath-ui-element name="openPageInEditor" + xpath="//fieldset[./legend/text()='Information (HTML page)']//a[.//text()='Open page in editor']" + description="Button open page in editor"/> asa unused --> + <!-- <xpath-ui-element name="replacePage" + xpath="//fieldset[./legend/text()='Information (HTML page)']//a[.//text()='Replace page']" + description="Button replace page"/> asa unused --> + <!-- TODO se overlay to create new page + <xpath-ui-element name="newHTMLpage" xpath="" description="Field new HTML page"/> + <xpath-ui-element name="createPage" xpath="" description="Button create html page "/> + <xpath-ui-element name="selectPage" xpath="" description="Button select page from storage folder"/> + <xpath-ui-element name="choosePage" xpath="" description="Radio Button before name of page"/> + <xpath-ui-element name="selectThisPage" xpath="" description="Button select this page"/> + --> + </pageset> + <pageset name="securitySettings" description="security settings when choosing html page for test, selftest, questionnaire or structure"> + <!-- <xpath-ui-element name="allowLinksStorageFolderYes" + xpath="//fieldset[./legend/text()='Security setting']//input[@name='allowRelativeLinks' and @value='true']" + description="Radio Button (Yes) allow links in the entire storage folder"/> asa unused --> + <!-- <xpath-ui-element name="allowLinksStorageFolderNo" + xpath="//fieldset[./legend/text()='Security setting']//input[@name='allowRelativeLinks' and @value='false']" + description="Radio Button (No) allow links in the entire storage folder"/> asa unused --> + <!-- <xpath-ui-element name="save" + xpath="//fieldset[./legend/text()='Security setting']//input[@value='Save']" + description="save button security setting"/> asa unused --> + </pageset> + <pageset name="groupBulk" description="group bulk paths"> + <xpath-ui-element name="createGroups" xpath="//div[@class='b_form_element_wrapper b_form_error b_clearfix'][descendant::text()='Learning groups']//div[@class='b_form_element']//a[@class='b_button']" description="create several groups"></xpath-ui-element> + <xpath-ui-element name="selectGroupsIfError" xpath="//div[@class='b_form_element_wrapper b_form_error b_clearfix'][descendant::text()='Learning groups']//div[@class='b_form_element']//input[@type='text']" description="select a bunch of groups if error message"></xpath-ui-element> + </pageset> + + </pageset> + + + </pageset> + + + +</ui-map-include> diff --git a/src/test/profile/selenium/ui-map/dmz-pageset.xml b/src/test/profile/selenium/ui-map/dmz-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba1f1057425476390a2360c1667e232947ae494b --- /dev/null +++ b/src/test/profile/selenium/ui-map/dmz-pageset.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="dmz" description="DMZ links"> + <xpath-ui-element name="login" xpath="//button[@value='Login']" description="login button" testcase="dmz/type(dmz::username,foo)/type(dmz::username,bar)/clickAndWait(dmz::login)"/> + + <xpath-ui-element name="disclaimerCheckbox" xpath="//input[@name='acknowledge_checkbox']" description="terms of use disclaimer - checkbox" /> + <xpath-ui-element name="acceptDisclaimer" xpath="//button[@value='" + acceptLabel + "']" description="terms of use disclaimer - accept button"> + <parameter name="acceptLabel" description="the name of the label"> + <defaultValue value="Accept"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="loginErrorOK" xpath="//button[.//text()='OK']" description="login error OK button"></xpath-ui-element> + <xpath-ui-element name="wayf" xpath="//div[@id='wayf_div']" description="wayf div"></xpath-ui-element> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/group-pageset.xml b/src/test/profile/selenium/ui-map/group-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..84e38c4dd72f362d4abd704338d6f3569c1b1173 --- /dev/null +++ b/src/test/profile/selenium/ui-map/group-pageset.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="group" description="configuration of a group"> + <pageset name="menu" description="group menu"> + <!-- default-testcase testcase="login/tabs::groups/groups::toolbox_create_projectGroup/type(groups::creategroup_groupName,tst)/type(groups::creategroup_groupDescription,tst)/groups::creategroup_save/tabs::closeGroup(nameOfGroup=tst)/groups::content_clickGroupEntry(nameOfGroup=tst)" final-command="clickAndWait"/--> + <xpath-ui-element name="course" xpath="//div[@class='b_tree']//a[contains(.//text(),'Course')]" description="course link in the group"></xpath-ui-element> + <xpath-ui-element name="startCourse" xpath="//div[@class='b_toolbox_content']//a[contains(.//text(),'Start')]" description="link to start course out of group"></xpath-ui-element> + <!--@TODO <xpath-ui-element xpath="" name="topLevelGroupMenu" description="top level node of group menu"> </xpath-ui-element>--> + <xpath-ui-element name="information" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Information']" description="information link in the group"></xpath-ui-element> + <xpath-ui-element name="calendar" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Calendar']" description="calendar link in the group"></xpath-ui-element> + <pageset name="calendar" description="calendar"> + <xpath-ui-element name="readOnly" xpath="//div[@class='o_cal_config_readonly' and @title='(Read only)']" description="read only element"/> + </pageset> + <xpath-ui-element name="members" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Members']" description="members link in the group"></xpath-ui-element> + <xpath-ui-element name="email" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='E-mail']" description="e-mail link in the group"></xpath-ui-element> + + <xpath-ui-element name="folder" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Folder']" description="folder link in the group"></xpath-ui-element> + <xpath-ui-element name="forum" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Forum']" description="forum link in the group"></xpath-ui-element> + <xpath-ui-element name="chat" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Chat']" description="chat link in the group"></xpath-ui-element> + <xpath-ui-element name="wiki" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Wiki']" description="wiki link in the group"></xpath-ui-element> + <xpath-ui-element name="portfolio" xpath="//div[@class='b_tree']//a[contains(@class, 'o_ep_icon')]" description="portfolio link in the group"></xpath-ui-element> + <xpath-ui-element name="administration" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Administration']" description="administration link in the group"></xpath-ui-element> + </pageset> + <pageset name="content" description="content edit group"> + <pageset name="description" description="description of project group"> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[contains(.//text(),'Description')]" name="tabDescription" description="tab description"></xpath-ui-element> + <pageset name="groupDetails" description="paragraph details"> + <xpath-ui-element name="groupName" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Group name']//div[@class='b_form_element']//input[@type='text']" description="flexi form element - group name"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//form[@name='businessGroupForm' or @name='createBuddygroupForm']//input[@value='Save']" name="save" description="save button description"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="//form[@name='businessGroupForm' or @name='createBuddygroupForm']//input[@value='Cancel']" name="cancel" description="cancel button description"></xpath-ui-element> asa unused --> + </pageset> + </pageset> + <pageset name="tools" description="tools of project group"> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Tools']" name="tabTools" description="tab tools"></xpath-ui-element> + <pageset name="collaborationTools" description="paragraph collaboration tools"> + <xpath-ui-element name="information" xpath="//div[@class='b_form_selection_element' and descendant::text()='Information for members']//input[@type='checkbox']" description="information checkbox"></xpath-ui-element> + <xpath-ui-element name="contactForm" xpath="//div[@class='b_form_selection_element' and descendant::text()='E-mail']//input[@type='checkbox']" description="contact form checkbox"></xpath-ui-element> + <xpath-ui-element name="calendar" xpath="//div[@class='b_form_selection_element' and descendant::text()='Calendar']//input[@type='checkbox']" description="calendar checkbox"></xpath-ui-element> + <xpath-ui-element name="folder" xpath="//div[@class='b_form_selection_element' and descendant::text()='Folder']//input[@type='checkbox']" description="folder checkbox"></xpath-ui-element> + <xpath-ui-element name="forum" xpath="//div[@class='b_form_selection_element' and descendant::text()='Forum']//input[@type='checkbox']" description="forum checkbox"></xpath-ui-element> + <xpath-ui-element name="chat" xpath="//div[@class='b_form_selection_element' and descendant::text()='Chat']//input[@type='checkbox']" description="chat checkbox"></xpath-ui-element> + <xpath-ui-element name="wiki" xpath="//div[@class='b_form_selection_element' and descendant::text()='Wiki']//input[@type='checkbox']" description="wiki checkbox"></xpath-ui-element> + <xpath-ui-element name="portfolio" xpath="//div[@class='b_form_selection_element' and descendant::text()='ePortfolio']//input[@type='checkbox']" description="eportfolio checkbox"></xpath-ui-element> + </pageset> + <pageset name="informationForMembers" description="paragraph information for members"> + <xpath-ui-element name="formFieldInformationMembers" xpath="//body[@id='tinymce']" description="form field information for members"></xpath-ui-element> + <xpath-ui-element name="save" xpath="//fieldset[./legend='Information for members']//div[@class='b_form_element']//button[@value='Save']" description="save button information for members"></xpath-ui-element> + </pageset> + <pageset name="calendarAccess" description="paragraph calendar access configuration"> + <xpath-ui-element name="calendarAccess" xpath="//div[@class='b_form_selection_element' and descendant::text()='" + label + "']//input[@type='radio']" description="calendar access"> + <parameter name="label" description="radio label"></parameter> + </xpath-ui-element> + <xpath-ui-element name="save" xpath="//fieldset[legend[text()='Configure calendar write permission']]//button[@value='Save']" description="save button calendar access"></xpath-ui-element> + </pageset> + </pageset> + <pageset name="members" description="members of project group"> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Members']" name="tabMembers" description="tab members"></xpath-ui-element> + <pageset name="displayMembers" description="paragraph display members"> + <!-- <xpath-ui-element xpath="ShowOwners" name="membersSeeOwners" description="checkbox members can see owners"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="ShowPartips" name="membersSeeParticipants" description="checkbox members can see participants"></xpath-ui-element> asa unused --> + + <!-- <xpath-ui-element xpath="//form[contains(@name, 'dmsForm')]//button[.//text()='Save']" name="save" description="save button"></xpath-ui-element> asa unused --> + + </pageset> + <!--@TODO evtl. auslagern commons <pageset name="owners" description="paragraph owners"> + <xpath-ui-element xpath="" name="" description="import user"></xpath-ui-element> + <xpath-ui-element xpath="" name="" description="add user(s)"></xpath-ui-element> + <xpath-ui-element xpath="" name="" description="remove button"></xpath-ui-element> + </pageset> + <pageset name="participants" description="paragraph participants"> + <xpath-ui-element xpath="" name="" description="import user"></xpath-ui-element> + <xpath-ui-element xpath="" name="" description="add user(s)"></xpath-ui-element> + <xpath-ui-element xpath="" name="" description="remove button"></xpath-ui-element> + </pageset>--> + </pageset> + <xpath-ui-element name="startCourse" xpath="//td//a[.//text()='Start']" description="starts first course in table"></xpath-ui-element> + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/groupAdministration-pageset.xml b/src/test/profile/selenium/ui-map/groupAdministration-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..3b939b296563c29a05dbd5fa92803546054b8c94 --- /dev/null +++ b/src/test/profile/selenium/ui-map/groupAdministration-pageset.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="groupAdministration" description="the group administration tab"> + + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/groupManagement-pageset.xml b/src/test/profile/selenium/ui-map/groupManagement-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..db91c8d2b4a93a39188fccc0dc61d5de5030d818 --- /dev/null +++ b/src/test/profile/selenium/ui-map/groupManagement-pageset.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="groupManagement" description="the group management of a course"> + <pageset name="menu" description="the left hand menu of the group management of a course"> + <!-- <xpath-ui-element name="groupManagement" xpath="//div[@class='b_tree']//ul/li//a[./text()='Group management']" description="left navigation link 'Group management'"/> asa unused --> + <!-- <xpath-ui-element name="administration" xpath="//div[@class='b_tree']//ul/li//a[./text()='Administration']" description="left navigation link 'Administration'"/> asa unused --> + <xpath-ui-element name="allLearningGroups" xpath="//div[@class='b_tree']//ul/li//a[./text()='All learning groups']" description="left navigation link 'All learning groups'"/> + <xpath-ui-element name="allLearningAreas" xpath="//div[@class='b_tree']//ul/li//a[./text()='All learning areas']" description="left navigation link 'All learning areas'"/> + <xpath-ui-element name="allMembers" xpath="//div[@class='b_tree']//ul/li//a[./text()='All members']" description="left navigation link 'All members'"/> + </pageset> + + <pageset name="content" description="the content area of the group management of a course"> + <pageset name="learningAreaTable" description="the learning area table"> + <xpath-ui-element name="editLearningArea" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfLearningArea + "']//a[.//text()='Edit']" description="Click on the Edit link of a particular learning area"> + <parameter name="nameOfLearningArea" description="the name of the learning area"/> + </xpath-ui-element> + <xpath-ui-element name="deleteLearningArea" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfLearningArea + "']//a[.//text()='Delete']" description="Click on the Delete link of a particular learning area"> + <parameter name="nameOfLearningArea" description="the name of the learning area"/> + + </xpath-ui-element> + </pageset> + <pageset name="learningGroupTable" description="the learning group table"> + <xpath-ui-element name="editLearningGroup" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfLearningGroup + "']//a[.//text()='Edit']" description="Click on the Edit link of a particular learning group"> + <parameter name="nameOfLearningGroup" description="the name of the learning group"/> + </xpath-ui-element> + <xpath-ui-element name="deleteLearningGroup" xpath="//div[.//a/@class='b_table_download']//table//tr[.//td//text()='" + nameOfLearningGroup + "']//a[.//text()='Delete']" description="Click on the Delete link of a particular learning group"> + <parameter name="nameOfLearningGroup" description="the name of the learning group"/> + </xpath-ui-element> + <xpath-ui-element name="selectGroup" xpath="//form//table//tr//td//a[descendant::text()='" + nameOfGroup + "']" description="select this group"> + <parameter name="nameOfGroup" description="the name of the group"/> + </xpath-ui-element> + </pageset> + + <pageset name="learningGroupsEditor" description="the learning groups editor"> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'group')]/following-sibling::div//input[@name='fe_bgName']" name="name" description="the name of the learning group - input field"/> asa unused --> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'group')]/following-sibling::div//textarea[@name='fe_bgWkDescription']" name="description" description="the description of the learning group - input field"/> asa unused --> + <xpath-ui-element name="maxParticipants" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::label[contains(text(),'Maximum')]]//div[@class='b_form_element']//input[@type='text']" description="the max number field of the learning group editor"/> + + <xpath-ui-element name="enableWaitinglist" xpath="//div[@class='b_form_selection_element'][descendant::text()='Waiting list']//input[@type='checkbox']" description="the enableWaitinglist checkbox of the learning group editor"/> + + <xpath-ui-element name="moveUpAutomatically" xpath="//div[@class='b_form_selection_element'][descendant::text()='Moving up automatically']//input[@type='checkbox']" description="the moveUpAutomatically checkbox of the learning group editor"/> + + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'group')]/following-sibling::div//input[@value='Save']" name="save" description="the save button of the learning group editor"/> asa unused --> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'group')]/following-sibling::div//input[@value='Cancel']" name="cancel" description="the cancel button of the learning group editor"/> asa unused --> + + <pageset name="addMembers" description="add member to learning group"> + <xpath-ui-element name="addTutor" xpath="//fieldset[contains(./legend/text(),'Tutors')]//a[descendant::text()='Add user(s)']" description="add tutor to group"/> + <xpath-ui-element name="checkUser" xpath="//fieldset[contains(./legend/text(),'Search along with user attributes')]//form//table//tr//td[.//text()='" + username + "']/../td[1]//input[@type='checkbox']" description="add tutor to group"> + <parameter name="username" description="username"/> + </xpath-ui-element> + </pageset> + </pageset> + <pageset name="learningAreaEditor" description="the learning area editor"> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'area')]/following-sibling::div//input[@name='name']" name="name" description="the name of the learning area - input field"/> asa unused --> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'area')]/following-sibling::div//textarea[@name='description']" name="description" description="the description of the learning area - input field"/> asa unused --> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'area')]/following-sibling::div//input[@value='Save']" name="save" description="the save button of the learning area editor"/> asa unused --> + <!-- <xpath-ui-element xpath="descendant::node()[@class='b_with_small_icon_left b_group_icon' and contains(text(),'area')]/following-sibling::div//input[@value='Cancel']" name="cancel" description="the cancel button of the learning area editor"/> asa unused --> + + <pageset name="tabs" description="tabs within learningAreaEditor"> + <!-- <xpath-ui-element name="description" xpath="//div[contains(./h4/@class, 'b_group_icon')]//div[@class='b_tabbedpane_tabs']//a[.//text()='Description']" description="tab group assignment"/> asa unused --> + <xpath-ui-element name="groupAssignment" xpath="//div[contains(./h4/@class, 'b_group_icon')]//div[@class='b_tabbedpane_tabs']//a[.//text()='Group assignment']" description="tab group assignment"/> + </pageset> + + <pageset name="groupAssignment" description="group assignment"> + <xpath-ui-element name="checkLearningGroup" xpath="//form[contains(@name, 'groupsChoice')]/table/tbody/tr[./td/text()='"+nameOfGroup+"']/td/input[@type='checkbox']" description="checkbox for selecting learning groups"> + <parameter name="nameOfGroup" description="the name of the learning group"/> + </xpath-ui-element> + <xpath-ui-element name="save" xpath="//form[contains(@name, 'groupsChoice')]/table/tbody/tr/td/div/input[@value='Save']" description="save button of the learning area group assignment"/> + <!-- <xpath-ui-element name="cancel" xpath="//form[contains(@name, 'groupsChoice')]/table/tbody/tr/td/div/input[@value='Cancel']" description="cancel button of the learning area group assignment"/> asa unused --> + </pageset> + </pageset> + <pageset name="userDetails" description="user details table"> + <xpath-ui-element name="removeFromGroup" xpath="//table[..//text()='Supervised groups']//tr[./td[2]='" + nameOfGroup + "']//a[.//text()='Remove']" + description="remove this user from a group"> + <parameter name="nameOfGroup" description="the name of the group"></parameter> + </xpath-ui-element> + </pageset> + </pageset> + <pageset name="toolbox" description="the toolbox area to the right"> + <pageset name="groupManagement" description="group management toolbox"> + <xpath-ui-element name="newLearningGroup" xpath="//div[@class='b_toolbox'][descendant::text()='Group management']//a[descendant::text()='New learning group']" description="Create new learning group link"/> + <pageset name="formNewLearningGroup" description="create new learning group"> + <xpath-ui-element name="name" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Group name']//div[@class='b_form_element']//input[@type='text']" description="the name of the learning group - input field"/> + <xpath-ui-element name="maxParticipants" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::label[contains(text(),'Maximum')]]//div[@class='b_form_element']//input[@type='text']" description="the max number field of the new learning group"/> + <xpath-ui-element name="enableWaitinglist" xpath="//div[@class='b_form_selection_element'][descendant::text()='Waiting list']//input[@type='checkbox']" description="the enableWaitinglist checkbox of the new learning group"/> + <xpath-ui-element name="moveUpAutomatically" xpath="//div[@class='b_form_selection_element'][descendant::text()='Moving up automatically']//input[@type='checkbox']" description="the moveUpAutomatically checkbox of the new learning group"/> + <xpath-ui-element name="save" xpath="//button[@value='Finish']" description="the finish button of the new learning group"/> + <!-- TODO:ld - cancel - has been changed --> + <!-- <xpath-ui-element name="cancel" xpath="//form[@name='groupForm']//input[@value='Cancel']" description="the cancel button of the new learning group"/> asa unused --> + </pageset> + <xpath-ui-element name="newLearningArea" xpath="//div[@class='b_toolbox'][descendant::text()='Group management']//a[descendant::text()='New learning area']" description="Create new learning area link"/> + <pageset name="formNewLearningArea" description="create new learning area"> + <xpath-ui-element name="name" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Name of learning area ']//div[@class='b_form_element']//input[@type='text']" description="the name of the learning area - input field"/> + </pageset> + + <xpath-ui-element name="close" xpath="//div[@class='b_toolbox'][descendant::text()='Group management']//a[descendant::text()='Close']" description="Close Group Management"/> + + </pageset> + <pageset name="createLists" description="create lists toolbox"> + <!-- <xpath-ui-element name="participantsInGroup" xpath="//div[@class='b_toolbox'][descendant::text()='Create lists']//a[descendant::text()='Participants in groups']" description="Create list with participants in group link"/> asa unused --> + <!-- <xpath-ui-element name="participantsInLearningAreas" xpath="//div[@class='b_toolbox'][descendant::text()='Create lists']//a[descendant::text()='Participants in learning areas']" description="Create list with participants in learning areas"/> asa unused --> + </pageset> + <pageset name="actions" description="actions group toolbox"> + <!-- <xpath-ui-element name="eMailToMember" xpath="//div[@class='b_toolbox'][descendant::text()='Actions group']//a[descendant::text()='E-mail to members']" description="E-Mail to members link"/> asa unused --> + <!-- <xpath-ui-element name="start" xpath="//div[@class='b_toolbox'][descendant::text()='Actions group']//a[descendant::text()='Start']" description="Start link"/> asa unused --> + <!-- <xpath-ui-element name="copy" xpath="//div[@class='b_toolbox'][descendant::text()='Actions group']//a[descendant::text()='Copy']" description="Copy link"/> asa unused --> + <!-- <xpath-ui-element name="copyMoreThanOnce" xpath="//div[@class='b_toolbox'][descendant::text()='Actions group']//a[descendant::text()='Copy more than once']" description="Copy more than once link"/> asa unused --> + <!-- <xpath-ui-element name="delete" xpath="//div[@class='b_toolbox'][descendant::text()='Actions group']//a[descendant::text()='Delete']" description="Delete link"/> asa unused --> + </pageset> + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/groups-pageset.xml b/src/test/profile/selenium/ui-map/groups-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9d1315a42751c0229570a080f76e229dcbc4540 --- /dev/null +++ b/src/test/profile/selenium/ui-map/groups-pageset.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="groups" description="Groups"> + <pageset name="menu" description="the left hand menu"> + <!-- <xpath-ui-element name="groups" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_groups']]//div[@class='b_tree']//a[descendant-or-self::text()='Groups']" description="left navigation link 'Groups'"/> asa unused --> + <xpath-ui-element name="myProjectGroups" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_groups']]//div[@class='b_tree']//a[descendant-or-self::text()='My project groups']" description="left navigation link 'My project groups'"/> + <!-- <xpath-ui-element name="myLearningGroups" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_groups']]//div[@class='b_tree']//a[descendant-or-self::text()='My learning groups']" description="left navigation link 'My learning groups'"/> asa unused --> + <!-- <xpath-ui-element name="myRightGroups" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_groups']]//div[@class='b_tree']//a[descendant-or-self::text()='My right groups']" description="left navigation link 'My right groups'"/> asa unused --> + </pageset> + + <pageset name="toolbox" description="the toolbox to the right"> + <pageset name="create" description="the 'create' toolbox to the right"> + <xpath-ui-element name="projectGroup" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Project group']" description="Create Project Group link"/> + </pageset> + <pageset name="delete" description="the 'delete' toolbox to the right"> + <!-- <xpath-ui-element name="projectGroups" xpath="//div[@class='b_toolbox'][descendant::text()='Delete']//a[descendant::text()='Project groups']" description="Delete Project Group link"/> asa unused --> + </pageset> + </pageset> + <!-- (se:) Diese Links sollten auch fuer Lerngruppen und Rechtegruppen funktionieren --> + <pageset name="content" description="content groups"> + <xpath-ui-element xpath="//tr[.//a[text()='" + nameOfGroup + "']]//a[contains(@href, 'Launch')]" name="clickGroupEntry" description="link of name of group"> + <parameter name="nameOfGroup" description="name of the group"><defaultValue value="test"/></parameter> + </xpath-ui-element> + <xpath-ui-element xpath="//tr[.//a[text()='" + nameOfGroup + "']]//a[contains(@href, 'Leave')]" name="leaveGroup" description="leave group"> + <parameter name="nameOfGroup" description="name of the group"/> + </xpath-ui-element> + <xpath-ui-element xpath="//tr[.//a[text()='" + nameOfGroup + "']]//a[contains(@href, 'Delete')]" name="deleteGroup" description="delete group"> + <parameter name="nameOfGroup" description="name of the group"/> + </xpath-ui-element> + <xpath-ui-element xpath="//div[contains(.//text(), 'If you leave')]/..//a[.//text()='Yes']" name="leaveYes" description="confirm yes of dialog when leaving group"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'If you leave')]/..//a[.//text()='No']" name="leaveNo" description="confirm no dialog when leaving group"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'If you leave')]/../../../..//a[@class='b_link_close']" name="leaveClose" description="close overlay dialog when leaving group"></xpath-ui-element> asa unused --> + <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/..//a[.//text()='Yes']" name="deleteYes" description="confirm yes of dialog when deleting group"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/..//a[.//text()='No']" name="deleteNo" description="confirm no dialog when deleting group"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/../../../..//a[@class='b_link_close']" name="deleteClose" description="close overlay dialog when deleting group"></xpath-ui-element> asa unused --> + + <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/..//a[.//text()='Yes']" name="deleteYesLs" description="confirm yes of dialog when deleting learning resource"></xpath-ui-element> + + <xpath-ui-element xpath="//div[contains(@class, 'b_table_wrapper')]//tr[1]/td[contains(.//text(), 'Delete')]//a" name="deleteFirstGroup" description="Delete the first group in the table"/> + </pageset> + + + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/home-pageset.xml b/src/test/profile/selenium/ui-map/home-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..f9ec3b7b384a9c8f42bf05ee6efb7f1111dd5a6a --- /dev/null +++ b/src/test/profile/selenium/ui-map/home-pageset.xml @@ -0,0 +1,202 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="home" description="The home page"> + <pageset name="menu" description="the left hand menu"> + <default-testcase testcase="login" final-command="clickAndWait"/> + <!-- <xpath-ui-element name="home" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Home']" description="left navigation link 'Home'"/> asa unused --> + <xpath-ui-element name="settings" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Settings']" description="left navigation link 'Settings'"/> + <xpath-ui-element name="einstellungen" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Einstellungen']" description="left navigation link 'Einstellungen'" testcase=""/> <!-- testcase only works in German... --> + <!-- <xpath-ui-element name="calendar" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Calendar']" description="left navigation link 'Calendar'"/> asa unused --> + <!-- <xpath-ui-element name="notifications" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Notifications']" description="left navigation link 'Notifications'"/> asa unused --> + <!-- <xpath-ui-element name="bookmarks" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Bookmarks']" description="left navigation link 'Bookmarks'"/> asa unused --> + <xpath-ui-element name="personalFolder" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Personal folder']" description="left navigation link 'Personal folder'"/> + <!-- <xpath-ui-element name="notes" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Notes']" description="left navigation link 'Notes'"/> asa unused --> + <xpath-ui-element name="evidencesOfAchievement" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Evidences of achievement']" description="left navigation link 'Evidences of achievement'"/> + <xpath-ui-element name="otherUsers" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='Other users']" description="left navigation link 'Other users'"/> + <xpath-ui-element name="ePortfolio" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='ePortfolio']" description="left navigation link 'ePortfolio'"/> + </pageset> + <pageset name="content" description="the (center) content area"> + + <!-- 'einstellungen' is only used for switching to English --> + <pageset name="einstellungen" description="the einstellungen content area"> + <pageset name="tabs" description="the einstellungen tabs"> + <xpath-ui-element name="system" xpath="//div[./h4/text()='Einstellungen']//div[@class='b_tabbedpane_tabs']//a[.//text()='System']" description="the Einstellungen-System tab"/> + </pageset> + <pageset name="system" description="system panel"> + <xpath-ui-element name="sprache" xpath="//fieldset[legend/text()='Allgemeine Systemeinstellungen']//select[@name='form.language_SELBOX']" description="language checkbox"/> + <xpath-ui-element name="speichern" xpath="//fieldset[legend/text()='Allgemeine Systemeinstellungen']//button[@value='Speichern']" description="The save button of the general system settings area"/> + </pageset> + </pageset> + + <pageset name="settings" description="the settings content area"> + <pageset name="tabs" description="the settings tabs"> + <default-testcase testcase="login/tabs::home/home::menu_settings/" final-command="clickAndWait"/> + <xpath-ui-element name="profile" xpath="//div[./h4/text()='Settings']//div[@class='b_tabbedpane_tabs']//a[.//text()='Profile']" description="the Settings-Profile tab" testcase="login/tabs::home/home::menu_settings/home::content_settings_tabs_system/home::content_settings_tabs_profile"/> + + <xpath-ui-element name="system" xpath="//div[./h4/text()='Settings']//div[@class='b_tabbedpane_tabs']//a[.//text()='System']" description="the Settings-System tab"/> + <xpath-ui-element name="password" xpath="//div[./h4/text()='Settings']//div[@class='b_tabbedpane_tabs']//a[.//text()='Password']" description="the Settings-Password tab"/> + <xpath-ui-element name="instantMessaging" xpath="//div[./h4/text()='Settings']//div[@class='b_tabbedpane_tabs']//a[.//text()='Instant Messaging']" description="the Settings-Instant Messaging tab"/> + </pageset> + <pageset name="profile" description="profile panel"> + <default-testcase testcase="login/home::menu_settings/" final-command="type(foo)"/> + <xpath-ui-element name="help" xpath="//a[@class='b_contexthelp']" description="help in user profile" testcase="login/home::menu_settings/click(home::content_settings_profile_help)"/> + <!-- <xpath-ui-element name="eMailAddress" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='E-mail address']//div[@class='b_form_element']//input[@type='text']" description="e-mail address field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="birthDate" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Date of birth']//div[@class='b_form_element']//input[@type='text']" description="date of birth field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="gender" xpath="//fieldset[./legend/text()='User profile']//select[@name='gender']" description="gender field" testcase=""></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="phonePrivate" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Phone number private']//div[@class='b_form_element']//input[@type='text']" description="phone private field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="phoneMobile" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Phone number mobile']//div[@class='b_form_element']//input[@type='text']" description="phone mobile field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="phoneOffice" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Phone number office']//div[@class='b_form_element']//input[@type='text']" description="phone office field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="skype" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Skype ID']//div[@class='b_form_element']//input[@type='text']" description="skype id field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="homepage" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Homepage']//div[@class='b_form_element']//input[@type='text']" description="homepage field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="street" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Street']//div[@class='b_form_element']//input[@type='text']" description="street field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="extraAddress" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Extra address line']//div[@class='b_form_element']//input[@type='text']" description="extra address field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="poBox" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='P.O. Box']//div[@class='b_form_element']//input[@type='text']" description="PO box field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="zipCode" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Zip code']//div[@class='b_form_element']//input[@type='text']" description="zip code field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="region" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Region/canton']//div[@class='b_form_element']//input[@type='text']" description="region field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="city" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='City']//div[@class='b_form_element']//input[@type='text']" description="city field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="country" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Country']//div[@class='b_form_element']//input[@type='text']" description="country field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='User profile']//input[@value='Save']" description="save button" testcase=""></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='User profile']//input[@value='Cancel']" description="cancel button" testcase=""></xpath-ui-element> asa unused --> + <xpath-ui-element name="yesLink" xpath="//a[contains(.//text(),'Yes')]" description="Yes link, at confirm change email"></xpath-ui-element> + </pageset> + <!--<pageset name="myVisitingCard" description="visiting card panel"> + <testcase-macro name="goToMyVisitingCard"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="home::menu_settings()"/> + <selenium command="clickAndWait" target="ui=home::content_settings_tabs_myVisitingCard"/> + </testcase-macro> + <default-testcase testcase="goToMyVisitingCard" final-command="check"/> + <xpath-ui-element name="help" xpath="//fieldset[./legend/text()='Configuration of visiting card']//div[@class='b_contexthelp_wrapper']" description="help in user profile" testcase="goToMyVisitingCard/click(home::content_settings_myVisitingCard_help)"/> + <xpath-ui-element name="firstName" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='firstName']" description="first name" testcase="goToMyVisitingCard/check(home::content_settings_myVisitingCard_firstName)"></xpath-ui-element> + <xpath-ui-element name="lastName" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='lastName']" description="last name"></xpath-ui-element> + <xpath-ui-element name="eMailAddress" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='email']" description="email address"></xpath-ui-element> + <xpath-ui-element name="birthDate" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='birthDay']" description="date of birth"></xpath-ui-element> + <xpath-ui-element name="gender" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='gender']" description="gender"></xpath-ui-element> + <xpath-ui-element name="phonePrivate" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='telPrivate']" description="phone private"></xpath-ui-element> + <xpath-ui-element name="phoneMobile" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='telMobile']" description="phone mobile"></xpath-ui-element> + <xpath-ui-element name="phoneOffice" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='telOffice']" description="phone office"></xpath-ui-element> + <xpath-ui-element name="skype" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='skype']" description="skype id"></xpath-ui-element> + <xpath-ui-element name="homepage" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='homepage']" description="homepage"></xpath-ui-element> + <xpath-ui-element name="street" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='street']" description="street"></xpath-ui-element> + <xpath-ui-element name="extraAddress" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='extendedAddress']" description="extra address"></xpath-ui-element> + <xpath-ui-element name="poBox" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='poBox']" description="PO box"></xpath-ui-element> + <xpath-ui-element name="zipCode" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='zipCode']" description="zip code"></xpath-ui-element> + <xpath-ui-element name="region" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='region']" description="region"></xpath-ui-element> + <xpath-ui-element name="city" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='city']" description="city"></xpath-ui-element> + <xpath-ui-element name="country" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='country']" description="country"></xpath-ui-element> + <xpath-ui-element name="institution" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='institutionalName']" description="institution"></xpath-ui-element> + <xpath-ui-element name="institutionID" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='institutionalUserIdentifier']" description="institution id"></xpath-ui-element> + <xpath-ui-element name="institutionMail" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='institutionalEmail']" description="institution e-mail"></xpath-ui-element> + <xpath-ui-element name="orgUnit" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='orgUnit']" description="organizational unit"></xpath-ui-element> + <xpath-ui-element name="studyField" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='studySubject']" description="field of studies"></xpath-ui-element> + <xpath-ui-element name="personalText" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@name='textAboutMe']" description="personal text" testcase="goToMyVisitingCard/type(home::content_settings_myVisitingCard_firstName, foo)"></xpath-ui-element> + <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@value='Save']" description="save button" testcase="goToMyVisitingCard/home::content_settings_myVisitingCard_save"></xpath-ui-element> + <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='Configuration of visiting card']//input[@value='Cancel']" description="cancel button" testcase="goToMyVisitingCard/home::content_settings_myVisitingCard_cancel"></xpath-ui-element> + + <xpath-ui-element name="fileUploadInput" xpath="//fieldset[contains(./legend/text(),'Published image')]//input[@title='Select file']" description="file upload text input" testcase="goToMyVisitingCard/type(home::content_settings_myVisitingCard_fileUploadInput, foo)"></xpath-ui-element> + <xpath-ui-element name="submit" xpath="//fieldset[contains(./legend/text(),'Published image')]//button[@value='Submit']" description="sumbit button" testcase="goToMyVisitingCard/home::content_settings_myVisitingCard_submit"></xpath-ui-element> + </pageset>--> + <pageset name="system" description="system panel"> + <testcase-macro name="goToSystem"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="home::menu_settings()"/> + <selenium command="clickAndWait" target="ui=home::content_settings_tabs_system"/> + </testcase-macro> + <pageset name="general" description="the general system settings area"> + <xpath-ui-element name="help" xpath="//fieldset[./legend/text()='General system settings']//div[@class='b_contexthelp_wrapper']" description="help in general system settings" testcase="goToSystem/click(home::content_settings_system_general_help)"/> + <xpath-ui-element name="language" xpath="//fieldset[legend/text()='General system settings']//div[@id='ber_languagepreferencesform']//select" description="language checkbox" testcase="goToSystem/select(home::content_settings_system_general_language,English)"/> + <xpath-ui-element name="fontSize" xpath="//fieldset[legend/text()='General system settings']//div[@id='ber_fontsizepreferencesform']//select" description="the character set used in download-combobox" testcase="goToSystem/select(home::content_settings_system_general_fontSize,Large)"/> + <xpath-ui-element name="characterSet" xpath="//fieldset[legend/text()='General system settings']//div[@id='ber_selectionpreferencesform']//select" description="the font size combobox" testcase="goToSystem/select(home::content_settings_system_general_characterSet,ISO-8859-2)"/> + <xpath-ui-element name="save" xpath="//fieldset[legend/text()='General system settings']//input[@value='Save']" description="The save button of the general system settings area" testcase="goToSystem/home::content_settings_system_general_save"/> + <xpath-ui-element name="cancel" xpath="//fieldset[legend/text()='General system settings']//input[@value='Cancel']" description="The cancel button of the general system settings area" testcase="goToSystem/home::content_settings_system_general_cancel"/> + </pageset> + <pageset name="ajax" description="the web 2.0/ajax settings area"> + <xpath-ui-element name="help" xpath="//fieldset[contains(./legend/text(),'WEB 2.0 / AJAX')]//div[@class='b_contexthelp_wrapper']//a" description="help in ajax section" testcase="goToSystem/click(home::content_settings_system_ajax_help)"/> + <xpath-ui-element name="mode" xpath="//fieldset[contains(./legend/text(),'WEB 2.0 / AJAX')]//input[@name='ajaxon']" description="ajax mode" testcase="goToSystem/check(home::content_settings_system_ajax_mode)"/> + <xpath-ui-element name="save" xpath="//fieldset[contains(./legend/text(),'WEB 2.0 / AJAX')]//input[@value='Save']" description="The save button of the ajax area" testcase="goToSystem/home::content_settings_system_ajax_save"/> + </pageset> + <pageset name="accessibility" description="the accessibility settings area"> + <xpath-ui-element name="web2amode" xpath="//fieldset[contains(./legend/text(),'Accessibility')]//input[@name='web2aModeOn']" description="web 2.a mode" testcase="goToSystem/check(home::content_settings_system_accessibility_web2amode)"/> + <xpath-ui-element name="save" xpath="//fieldset[contains(./legend/text(),'Accessibility')]//input[@value='Save']" description="The save button of the accessibility area" testcase="goToSystem/home::content_settings_system_accessibility_save"/> + </pageset> + <pageset name="replayMode" description="the replay mode settings area"> + <xpath-ui-element name="web2amode" xpath="//fieldset[contains(./legend/text(),'Replay mode')]//input[@name='checkbox']" description="web 2.a mode" testcase="goToSystem/check(home::content_settings_system_replayMode_web2amode)"/> + </pageset> + </pageset> + <pageset name="password" description="password panel"> + <testcase-macro name="goToPassword"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="home::menu_settings()"/> + <selenium command="clickAndWait" target="ui=home::content_settings_tabs_password"/> + </testcase-macro> + <xpath-ui-element name="oldPassword" xpath="//fieldset[./legend/text()='Change your OLAT password']//input[@name='passwordold']" description="old OLAT password" testcase="goToPassword/type(home::content_settings_password_oldPassword,tst)"></xpath-ui-element> + <xpath-ui-element name="newPassword" xpath="//fieldset[./legend/text()='Change your OLAT password']//input[@name='passwordnew1']" description="new OLAT password" testcase="goToPassword/type(home::content_settings_password_newPassword,tst)"></xpath-ui-element> + <xpath-ui-element name="newPasswordConfirm" xpath="//fieldset[./legend/text()='Change your OLAT password']//input[@name='passwordnew2']" description="confirm new OLAT password" testcase="goToPassword/type(home::content_settings_password_newPasswordConfirm,tst)"></xpath-ui-element> + <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='Change your OLAT password']//input[@value='Save']" description="save button" testcase="goToPassword/home::content_settings_password_save"></xpath-ui-element> + <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='Change your OLAT password']//input[@value='Cancel']" description="cancel button" testcase="goToPassword/home::content_settings_password_cancel"></xpath-ui-element> + </pageset> + <pageset name="instantMessaging" description="instant messaging panel"> + <testcase-macro name="goToInstantMessaging"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="home::menu_settings()"/> + <selenium command="clickAndWait" target="ui=home::content_settings_tabs_instantMessaging"/> + </testcase-macro> + <pageset name="userlist" description="the online user list section of the instant messaging panel"> + <xpath-ui-element name="userNameVisible" xpath="//fieldset[./legend/text()='Online user list (Click to start chat)']//input[@name='onlineList' and @value='true']" description="user name visible (true) radio box" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_userlist_userNameVisible)"></xpath-ui-element> + <xpath-ui-element name="userNameInvisible" xpath="//fieldset[./legend/text()='Online user list (Click to start chat)']//input[@name='onlineList' and @value='false']" description="user name visible (false) radio box" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_userlist_userNameInvisible)"></xpath-ui-element> + <xpath-ui-element name="onlineTimeVisible" xpath="//fieldset[./legend/text()='Online user list (Click to start chat)']//select[@name='onlineTime']" description="online time visible" testcase="goToInstantMessaging/select(home::content_settings_instantMessaging_userlist_onlineTimeVisible,Yes)"></xpath-ui-element> + <xpath-ui-element name="courseNameVisible" xpath="//fieldset[./legend/text()='Online user list (Click to start chat)']//select[@name='courseName']" description="course visible" testcase="goToInstantMessaging/select(home::content_settings_instantMessaging_userlist_courseNameVisible,Yes)"></xpath-ui-element> + <!-- <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='COnline user list (Click to start chat)']//input[@value='Save']" description="save button"/> asa unused --> + <!-- <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='COnline user list (Click to start chat)']//input[@value='Cancel']" description="cancel button"/> asa unused --> + </pageset> + <pageset name="roster" description="the roster section of the instant messaging panel"> + <default-testcase testcase="goToInstantMessaging" final-command="clickAndWait"/> + <xpath-ui-element name="statusAvailable" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='available']" description="the Available status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusAvailable)"/> + <xpath-ui-element name="statusChatWithMePlease" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='chat']" description="the I would like to chat status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusChatWithMePlease)"/> + <xpath-ui-element name="statusAbsent" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='away']" description="the Absent status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusAbsent)"/> + <xpath-ui-element name="statusLongAbsent" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='xa']" description="the Absent for longer status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusLongAbsent)"/> + <xpath-ui-element name="statusDoNotDisturb" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='dnd']" description="the Please do not disturb status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusDoNotDisturb)"/> + <xpath-ui-element name="statusNotAvailable" xpath="//fieldset[./legend/text()='Roster']//input[@type='radio' and @value='unavailable']" description="the Not available status" testcase="goToInstantMessaging/click(home::content_settings_instantMessaging_roster_statusNotAvailable)"/> + <!-- <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='Roster']//input[@value='Save']" description="save button"/> asa unused --> + <!-- <xpath-ui-element name="cancel" xpath="//fieldset[./legend/text()='Roster']//input[@value='Cancel']" description="cancel button"/> asa unused --> + </pageset> + </pageset> + </pageset> + <pageset name="evidencesOfAchievement" description="the evidencesOfAchievement content area"> + <xpath-ui-element name="passedStatus" xpath="//tr//td[contains(descendant::text(),'" + title + "')]/../td/span[@class='o_passed' or @class='o_notpassed']/text()" description="the Passed/Failed status"> + <parameter name="title" description="the title of the course"/> + </xpath-ui-element> + <xpath-ui-element name="selectDetails" xpath="//form//td[contains(descendant::text(),'" + title + "')]/../td/a[./text()='Show']" description="selects Details link"> + <parameter name="title" description="the title of the course"> + <defaultValue value="AssessmentTool"/> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="startCourse" xpath="//tr//td[contains(descendant::text(),'" + title + "')]/../td/a[./text()='Start course']" description="Start course"> + <parameter name="title" description="the title of the course"/> + </xpath-ui-element> + <xpath-ui-element name="delete" xpath="//form//td[contains(descendant::text(),'" + title + "')]/../td/a[./text()='Delete']" description="Start course"> + <parameter name="title" description="the title of the course"/> + </xpath-ui-element> + <xpath-ui-element name="evidenceOfAchievement" xpath="//div[@class='o_efficiencystatement' and .//text()='Evidence of achievement']" description="the Evidence of achievement div"/> + </pageset> + <pageset name="portlets" description="portlets"> + <var-link-ui-element name="myBookmarks" linkparam="nameOfBookmark" description="Start bookmark from portlet"/> + <var-link-ui-element name="myGroups" linkparam="nameOfGroup" description="Start group from portlet"/> + <var-link-ui-element name="myNotifications" linkparam="nameOfNotification" description="Start notification from portlet"/> + <var-link-ui-element name="myEvidenceOfAchievement" linkparam="nameOfEvidenceOfAchievement" description="Start evidence of achievement from portlet"/> + <var-link-ui-element name="myNotes" linkparam="nameOfNote" description="Start note from portlet"/> + </pageset> + </pageset> + <pageset name="topNav" description="Top Navigation"> + <xpath-ui-element name="olatHelp" xpath="//div[@id='b_topnav']//a[@target='_help']" description="Starts the OLAT help"></xpath-ui-element> + </pageset> + <pageset name="config" description="Home configurator"> + <xpath-ui-element name="editConfig" xpath="//a[.//text()='Configure page']" description="start editing Home configuration"></xpath-ui-element> + <xpath-ui-element name="endConfig" xpath="//a[.//text()='End configuration']" description="end editing Home configuration"></xpath-ui-element> + <xpath-ui-element name="autoConfigMyGroups" xpath="//div[@class='b_portlet b_portlet_edit o_portlet_groups']//a[@class='b_portlet_edit_sort_auto']" description="start automatically config wizard"></xpath-ui-element> + <xpath-ui-element name="autoConfigMyBookmarks" xpath="//div[@class='b_portlet b_portlet_edit o_portlet_bookmark']//a[@class='b_portlet_edit_sort_auto']" description="start automatically config wizard for the bookmark portlet"/> + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/infoMessage-pageset.xml b/src/test/profile/selenium/ui-map/infoMessage-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..03e2452f4f18085a34662e9002381bf3309d7066 --- /dev/null +++ b/src/test/profile/selenium/ui-map/infoMessage-pageset.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <!-- Info message --> + <pageset name="infoMessage" description="Info message links"> + <xpath-ui-element name="createMessage" xpath="//div[@class='b_float_right o_infomsg_create_button']//a[@class='b_button']" description="create message button"/> + <xpath-ui-element name="finishMessage" xpath="//a[@class='b_button b_wizard_button_finish']" description="finish message button"/> + <!-- ltere Mitteilungen anzeigen --> + <xpath-ui-element name="olderMessage" xpath="//a[contains(.//text(),'Show older messages')]" description="show older messages"></xpath-ui-element> + <xpath-ui-element name="currentMessage" xpath="//a[contains(.//text(),'Show new messages')]" description="show current messages"></xpath-ui-element> + + <xpath-ui-element name="messageTitle" xpath="//div[@class='o_infomsg b_clearfix']//h5[descendant::text()='" + titleOfMessage + "']" description="title of the message"> + <parameter name="titleOfMessage" description="title of the message"/> + </xpath-ui-element> + + <xpath-ui-element name="editFirstMessage" xpath="//div[@class='o_infomsg b_clearfix'][1]//a[contains(.//text(),'Edit')]" description="edit first messages"></xpath-ui-element> + <xpath-ui-element name="deleteFirstMessage" xpath="//div[@class='o_infomsg b_clearfix'][1]//a[contains(.//text(),'Delete')]" description="delete first messages"></xpath-ui-element> + + <xpath-ui-element name="messageInEdition" xpath="//div[@class='b_window_content_wrapper']//legend[contains(.//text(),'Create message')]" description="is message edited"></xpath-ui-element> + <xpath-ui-element name="messageAlreadyEdited" xpath="//span[contains(.//text(),'This message is being edited by user')]" description="edit first messages"></xpath-ui-element> + + + </pageset> + +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/learningResources-pageset.xml b/src/test/profile/selenium/ui-map/learningResources-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..11afc0f5f671473fd099a9f56cee5fdf8e244fef --- /dev/null +++ b/src/test/profile/selenium/ui-map/learningResources-pageset.xml @@ -0,0 +1,254 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="learningResources" description="Learning Resources"> + <pageset name="menu" description="the left hand menu"> + <default-testcase testcase="login/tabs::learningResources" final-command="clickAndWait"/> + <!-- <xpath-ui-element name="learningResources" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Learning resources']" description="left navigation link 'Learning resources'"/> asa unused --> + <xpath-ui-element name="catalog" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Catalog']" description="left navigation link 'Catalog'"/> + <xpath-ui-element name="searchForm" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Search form']" description="left navigation link 'Search form'"/> + <xpath-ui-element name="myEntries" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='My entries']" description="left navigation link 'My entries'"/> + <xpath-ui-element name="courses" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Courses']" description="left navigation link 'Courses'"/> + <xpath-ui-element name="coursesMenuItemSelected" xpath="//a[@class=' b_tree_selected b_tree_l1' and descendant-or-self::text()='Courses']" description="menu item courses is selected"/> + <!-- <xpath-ui-element name="tests" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Tests']" description="left navigation link 'Tests'"/> asa unused --> + <!-- <xpath-ui-element name="questionnaires" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Questionnaires']" description="left navigation link 'Questionnaires'"/> asa unused --> + <!-- <xpath-ui-element name="cpLearningContent" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='CP learning content']" description="left navigation link 'CP learning content'"/> asa unused --> + <!-- <xpath-ui-element name="scormLearningContent" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='SCORM learning content']" description="left navigation link 'SCORM learning content'"/> asa unused --> + <!-- <xpath-ui-element name="resourceFolder" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Resource folder']" description="left navigation link 'Resource folder'"/> asa unused --> + <xpath-ui-element name="wikis" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Wikis']" description="left navigation link 'Wikis'"/> + <!-- <xpath-ui-element name="glossary" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Glossary']" description="left navigation link 'Glossary'"/> asa unused --> + <!-- new lrs for 6.3--> + <xpath-ui-element name="blog" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Blogs']" description="left navigation link 'Blogs'"/> + <xpath-ui-element name="podcast" xpath="//body[//*[@class='b_nav_site b_nav_active o_site_repository']]//div[@class='b_tree']//a[descendant-or-self::text()='Podcasts']" description="left navigation link 'Podcasts'"/> + + </pageset> + + <pageset name="content" description="the (center) content area"> + <testcase-macro name="login"> + <call-macro name="login"/> + </testcase-macro> + <testcase-macro name="listDemoCourse"> + <selenium command="clickAndWait" target="tabs::learningResources"/> + <selenium command="clickAndWait" target="learningResources::menu_searchForm"/> + <selenium command="type" target="learningResources::content_searchForm_titleField" value="Demo Course"/> + <selenium command="clickAndWait" target="learningResources::content_searchForm_search"/> + </testcase-macro> + <xpath-ui-element name="firstLearningResourceInTable" xpath="//div[h4/text()='Learning resources']//table//tr[1]//td[5]//a" description="refers to the first learning resource click in the table"/> + <!-- se clickCourseEntry sollte gelöscht werden --> + <xpath-ui-element name="clickCourseEntry" xpath="//a[contains(text(), '" + nameOfCourse + "')]" description="Click on the title of a course" testcase="login/listDemoCourse/learningResources::content_clickCourseEntry(nameOfCourse=Demo Course)"> + <parameter name="nameOfCourse" description="the name of the course"/> + </xpath-ui-element> + <xpath-ui-element name="clickLearningResource" xpath="//table//a[contains(text(), '" + nameOfLearningResource + "')]" description="Click on the title of a Learning resource" testcase="login/listDemoCourse/learningResources::content_clickLearningResource(nameOfLearningResource=Demo Course)"> + <parameter name="nameOfLearningResource" description="the name of the Learning resource"> + <defaultValue value="Demo Course" /> + <defaultValue value="Demo course wiki" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="clickCatalogEntry" xpath="//table//a[contains(*//text(), '" + nameOfLearningResource + "')]" description="Click on the title of a Learning resource" testcase="login/listDemoCourse/learningResources::content_clickLearningResource(nameOfLearningResource=Demo Course)"> + <parameter name="nameOfLearningResource" description="the name of the Learning resource" /> + </xpath-ui-element> + <!-- ki <xpath-ui-element name="goToContentOfLearningResource" xpath="//a[descendant-or-self::text()='" + nameOfLearningResource + "']/../..//a[descendant-or-self::text()='Go to content']" description="The Go to content link in a Learning Resources Table"> + <parameter name="nameOfLearningResource" description="the name of the Learning resource"> + <defaultValue value="Demo Course" /> + <defaultValue value="Demo course wiki" /> + </parameter> + </xpath-ui-element>--> + + <xpath-ui-element name="showDetailedView" xpath="//a[starts-with(text(), '" + nameOfLearningResource + "')]/../..//a[descendant-or-self::text()='Detailed view']" description="The Detailed view link in a Learning Resources Table, for the resource starting-with nameOfLearningResource"> + <parameter name="nameOfLearningResource" description="the name of the Learning resource"> + <defaultValue value="Demo Course" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="showContent" xpath="//a[descendant-or-self::text()='Show content' and @class='b_button']" description="The Show Content button in a Course Detailed View"/> + <xpath-ui-element name="selectedAccessLabel" xpath="//div[contains(.//label/text(), 'Access have')]//div[contains(@class,'b_form_selection_element')][.//input[@checked='checked']]//label" description="The label with the selected access rule" /> + <!-- <link-ui-element name="additionalInformation" link="Additional information" description="Additional Information Link"/> asa unused --> + <pageset name="searchForm" description="learning resources search form"> + <!-- <xpath-ui-element name="titleField" xpath="//form[@name='searchform']//input[@name='cif_displayname']" description="title of learning resource field"></xpath-ui-element> unused --> + <!-- <xpath-ui-element name="authorField" xpath="//form[@name='searchform']//input[@name='cif_author']" description="author of learning resource field"></xpath-ui-element> unused --> + <xpath-ui-element name="courseType" xpath="//input[@type='checkbox' and @value='CourseModule']" description="course type checkbox"/> + <!-- <xpath-ui-element name="descriptionField" xpath="//form[@name='searchform']//input[@name='cif_description']" description="description of learning resource field"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element name="search" xpath="//form[@name='searchform']//input[@value='Search']" description="search button learning resources search map"></xpath-ui-element> unused --> + </pageset> + <pageset name="courseTable" description="courses table"> + <xpath-ui-element name="selectCourse" xpath="//form//table//tr[" + index + "]/td[2]//a" description="select course in table"> + <parameter name="index" description="row in table"/> + </xpath-ui-element> + </pageset> + </pageset> + + <pageset name="toolbox" description="the toolbox area to the right"> + <pageset name="import" description="the import toolbox to the right"> + <default-testcase testcase="login/tabs::learningResources/learningResources::menu_myEntries" final-command="clickAndWait"/> + <xpath-ui-element name="course" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Course']" description="the import course link in the import toolbox"/> + <xpath-ui-element name="cpLearningContent" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='CP learning content']" description="the import CP learning content link in the import toolbox"/> + <!-- <xpath-ui-element name="scormLearningContent" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='SCORM learning content']" description="the import SCORM learning content link in the import toolbox"/> asa unused --> + <!-- <xpath-ui-element name="test" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Test']" description="the import Test link in the import toolbox"/> asa unused --> + <!-- <xpath-ui-element name="questionnaire" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Questionnaire']" description="the import questionnaire link in the import toolbox"/> asa unused --> + <!-- <xpath-ui-element name="wiki" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Wiki']" description="the import Wiki link in the import toolbox"/> asa unused --> + <!-- <xpath-ui-element name="glossary" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Glossary']" description="the import glossary link in the import toolbox"/> asa unused --> + <!-- <xpath-ui-element name="otherFormats" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Other formats']" description="the import other formats link in the import toolbox"/> asa unused --> + <!-- new for 6.3--> + <xpath-ui-element name="blog" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Blog']" description="the import blog link in the create toolbox"/> + <xpath-ui-element name="podcast" xpath="//div[@class='b_toolbox'][descendant::text()='Import']//a[descendant::text()='Podcast']" description="the import podcast link in the create toolbox"/> + </pageset> + <pageset name="create" description="the create toolbox to the right"> + <default-testcase testcase="login/tabs::learningResources/learningResources::menu_myEntries" final-command="clickAndWait"/> + <xpath-ui-element name="course" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Course']" description="the create course link in the create toolbox"/> + <xpath-ui-element name="test" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[contains(descendant::text(), 'Test')]" description="the create test link in the create toolbox"/> + <xpath-ui-element name="questionnaire" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Questionnaire']" description="the create questionnaire link in the create toolbox"/> + <xpath-ui-element name="resourceFolder" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Resource folder']" description="the create resource folder link in the create toolbox"/> + <xpath-ui-element name="wiki" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Wiki']" description="the create wiki link in the create toolbox"/> + <xpath-ui-element name="glossary" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Glossary']" description="the create glossary link in the create toolbox"/> + <!-- new for 6.3--> + <xpath-ui-element name="blog" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Blog']" description="the create blog link in the create toolbox"/> + <xpath-ui-element name="podcast" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[descendant::text()='Podcast']" description="the create podcast link in the create toolbox"/> + <xpath-ui-element name="createCP" xpath="//div[@class='b_toolbox'][descendant::text()='Create']//a[contains(./text(), 'CP')]" description="create CP link"/> + </pageset> + <pageset name="delete" description="the delete toolbox to the right"> + <!-- <xpath-ui-element name="learningResources" xpath="//div[@class='b_toolbox'][descendant::text()='Delete']//a[descendant::text()='Learning resources']" description="the delete learning resources link in the create toolbox"/> asa unused --> + </pageset> + <pageset name="category" description="the catagory toolbox to the right, menu catalog"> + <!-- <xpath-ui-element name="modifyData" xpath="//div[@class='b_toolbox'][descendant::text()='Category']//a[descendant::text()='Modify data']" description="the modify data link in the catagory toolbox"/> asa unused --> + <!-- <xpath-ui-element name="nominateAdministrator" xpath="//div[@class='b_toolbox'][descendant::text()='Category']//a[descendant::text()='Nominate administrator']" description="the nominate administrator link in the catagory toolbox"/> asa unused --> + <!-- <xpath-ui-element name="contactAdministrator" xpath="//div[@class='b_toolbox'][descendant::text()='Category']//a[descendant::text()='Contact administrator']" description="the contact administrator link in the catagory toolbox"/> asa unused --> + </pageset> + <pageset name="add" description="the add toolbox to the right, menu catalog"> + <!-- <xpath-ui-element name="subCategory" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Sub-category']" description="the sub-category link in the add toolbox"/> asa unused --> + <!-- <xpath-ui-element name="learningResource" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Learning resource']" description="the learning resource link in the add toolbox"/> asa unused --> + </pageset> + <pageset name="learningResource" description="the Learning resource toolbox to the right"> + <!-- <xpath-ui-element name="showContent" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Show content']" description="the show content link in the learning resource toolbox"/> asa unused --> + <xpath-ui-element name="exportContent" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Export content']" description="the edit content link in the learning resource toolbox"/> + <!-- <xpath-ui-element name="setBookmark" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Set bookmark']" description="the set bookmark link in the learning resource toolbox"/> asa unused --> + <xpath-ui-element name="editContent" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Edit content']" description="the edit content link in the learning resource toolbox"/> + <!-- <xpath-ui-element name="modifyDescription" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Modify description']" description="the modify description link in the learning resource toolbox"/> asa unused --> + <xpath-ui-element name="modifyProperties" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Modify settings']" description="the modify properties link in the learning resource toolbox"/> + <xpath-ui-element name="copy" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Copy']" description="the copy link in the learning resource toolbox"/> + <xpath-ui-element name="delete" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Delete']" description="the delete link in the learning resource toolbox"/> + <xpath-ui-element name="assignOwners" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Manage owners']" description="the Assign owners link in the learning resource toolbox"/> + <xpath-ui-element name="addToCatalog" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Add to catalog']" description="Add the learning resource to catalog" /> + <!-- <xpath-ui-element name="closeDetailedView" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Close detailed view']" description="the close detailed view link in the learning resource toolbox"/> asa unused --> + <xpath-ui-element name="closeCourse" xpath="//div[@class='b_toolbox'][descendant::text()='Learning resource']//a[descendant::text()='Close']" description="Close the course" /> + <pageset name="assignOwners" description="Assign owners of a learning resource"> + <xpath-ui-element name="addOwner" xpath="//a[contains(descendant::text(), 'Add user(s)')]" description="add user to owner list" /> + </pageset> + </pageset> + </pageset> + + <pageset name="dialog" description="all dialogs in learning resources"> + <xpath-ui-element name="title" xpath="//fieldset[./legend='Information on this entry']//input[@type='text']" description="title input field"/> + <xpath-ui-element name="description" xpath="//body[@id='tinymce']" description="description input field"/> + <!-- <xpath-ui-element name="next" xpath="//div[@class='b_button_group']//input[@value='Next']" description="Course title and description - next"/> asa unused --> + <xpath-ui-element name="buttonNext" xpath="//button[.//text()='Next']" description="Course title and description - next"/> + <xpath-ui-element xpath="//div[contains(.//text(), 'Do you want to start the editor?')]/..//a[.//text()='Yes']" name="startYes" description="confirm yes of dialog when starting the editor"></xpath-ui-element> + <xpath-ui-element xpath="//div[contains(.//text(), 'Do you want to start the editor?')]/..//a[.//text()='No']" name="startNo" description="confirm no of dialog when not starting the editor"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete this learning resource?')]/..//a[.//text()='Yes']" name="deleteYes" description="confirm yes of dialog when deleting a learning resource"></xpath-ui-element> asa unused --> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete this learning resource?')]/..//a[.//text()='No']" name="deleteNo" description="confirm no of dialog when deleting a learning resource"></xpath-ui-element> asa unused --> + + <xpath-ui-element name="yes" xpath="//div[@class='b_button_group']//a[descendant::text()='Yes']" description="the Yes button on the 'Configuration changed' dialog"/> + <xpath-ui-element name="catalogRoot" xpath="//div[contains(@class, 'b_modal_area')]//div[@id='extdd-1']//a[contains(@class, 'x-tree-node-anchor')]" description="Select the catalog root for inserting course" /> + </pageset> + + <pageset name="courseImport" description="the course import dialog"> + <xpath-ui-element name="uploadFile" xpath="//a[contains(./span/text(),'Upload file')]" description="the upload file button"/> + <xpath-ui-element name="fileChooser" xpath="//fieldset[//text()='File upload']//input[@class='b_fileinput_realchooser']" description="the file choose input field"/> + <!-- <xpath-ui-element name="fileChooserSave" xpath="//fieldset[./legend/text()='File upload']//input[@value='Save']" description="the save button under the file chooser input field"/> asa unused --> + <xpath-ui-element name="importReferencesImport" xpath="//div[./h4/text()='Learning resource of type Add course']//ul/li//a[.//text()='Import']" description="the import button in the import-reference dialog"/> + <xpath-ui-element name="importReferencesContinue" xpath="//div[@class='b_window' and .//text()='Learning resource of type Add course']//a[./span/text()='Continue course import']" description="the continue course import button in the import-reference dialog"/> + <xpath-ui-element name="wizardShowDetailsView" xpath="//input[@value='dv']" description="show detail view radio button"></xpath-ui-element> + <xpath-ui-element name="wizardStartCourseEditor" xpath="//input[@value='ce']" description="start course editor radio button"></xpath-ui-element> + </pageset> + <pageset name="courseWizard" description="the course wizard dialog"> + <xpath-ui-element name="selectWizardRadio" xpath="//input[@value='sw']" description="start the course wizard" /> + <xpath-ui-element name="createSinglePage" xpath="//input[@value='sp']" description="create a single page" /> + <xpath-ui-element name="createEnrollment" xpath="//input[@value='en']" description="create an enrollment" /> + <xpath-ui-element name="editEnrollmentLink" xpath="//div[@class='b_wizard']//table//a[span/text()='Edit']" description="edit the enrollment" /> + <xpath-ui-element name="createDownloadFolder" xpath="//input[@value='bc']" description="create a download folder" /> + <xpath-ui-element name="createForum" xpath="//input[@value='fo']" description="create a forum" /> + <xpath-ui-element name="createContactForm" xpath="//input[@value='co']" description="create a contact form" /> + <pageset name="editEnrollment" description="the Overlay for editing the enrollment"> + <xpath-ui-element name="number_learningGroups" xpath="//div[contains(@class,'b_modal_area')]//form//input[@type='text']" description="textfield for number of learning groups" /> + <xpath-ui-element name="number_learningGroups" xpath="//div[contains(@class,'b_modal_area')]//form//input[@type='text' and @value='25']" description="textfield for number participants" /> + <xpath-ui-element name="accessLimit" xpath="//input[@name='accessLimit']" description="checkbox for setting only registered users" /> + <xpath-ui-element name="selectSP" xpath="//input[@value='Information page']" description="select information page" /> + <xpath-ui-element name="selectBC" xpath="//input[@value='Download folder']" description="select download folder" /> + <xpath-ui-element name="selectFO" xpath="//input[@value='Forum']" description="select information page" /> + <xpath-ui-element name="selectCO" xpath="//input[@value='E-mail']" description="select information page" /> + </pageset> + <xpath-ui-element name="catalogRoot" xpath="//div[contains(@class, 'b_wizard')]//a[contains(@class, 'x-tree-node-anchor') and //text()='CATALOG ROOT']" description="Select the catalog root for inserting course" /> + </pageset> + <pageset name="closeCourseWizard" description="The Wizard to close a course"> + <xpath-ui-element name="cleanCatalog" xpath="//input[contains(@value,'form.clean.catalog')]" description="The checkbox to clean catalog" /> + <xpath-ui-element name="cleanGroup" xpath="//input[contains(@value,'form.clean.groups')]" description="the checkbox to clean groups" /> + </pageset> + + </pageset> + <pageset name="learningResourcesModifieProperties" description="modifie properties of a learing resource"> + <!-- <xpath-ui-element name="repoEntryAccess" xpath="//select[@name='cif_access']" description="repo entry access dropdown" /> unused --> + <xpath-ui-element name="accessOnlyOwners" xpath="//fieldset[./legend='Settings regarding learning resources']//input[@class='b_radio' and @name='cif_access' and @value='1']" description="access - only owners radio button"/> + <xpath-ui-element name="accessOwnersAndAuthors" xpath="//fieldset[./legend='Settings regarding learning resources']//input[@class='b_radio' and @name='cif_access' and @value='2']" description="access - owners and authors radio button"/> + <xpath-ui-element name="accessAllRegistered" xpath="//fieldset[./legend='Settings regarding learning resources']//input[@class='b_radio' and @name='cif_access' and @value='3']" description="access - all registered users radio button"/> + <xpath-ui-element name="accessRegisteredAndGuests" xpath="//fieldset[./legend='Settings regarding learning resources']//input[@class='b_radio' and @name='cif_access' and @value='4']" description="access - registered users and guests radio button"/> + <xpath-ui-element name="evidenceOfAchievement" xpath="//a[descendant::text()='Evidence of achievement']" description="select Evidence of achievement tab" /> + <xpath-ui-element name="evidenceOfAchievementEnabled" xpath="//input[@name='isOn']" description="Evidence of achievement enabled/disabled checkbox" /> + </pageset> + + <pageset name="blog" description="blog resource links"> + <xpath-ui-element name="create" xpath="//a[@class='b_button' and .//text()='Create your own entries']" description="create your own entries"/> + <xpath-ui-element name="createNewEntry" xpath="//a[.//text()='Create new entry']" description="Create new entry"/> + <xpath-ui-element name="editEntry" xpath="//a[contains(.//text(),'Edit entry') and ancestor::div//h5[contains(.//text(),'" + entryTitle + "')]]" description="edit entry"> + <parameter name="entryTitle" description="entry title"/> + </xpath-ui-element> + <xpath-ui-element name="draft" xpath="//div[@class='o_post b_clearfix o_draft']//h5[contains(.//text(),'" + entryTitle + "')]" description="draft with title"> + <parameter name="entryTitle" description="entry title"/> + </xpath-ui-element> + <xpath-ui-element name="addComment" xpath="//a[@class='b_comments' and ancestor::div//h5[contains(.//text(),'" + entryTitle + "')]]" description="comments link"> + <parameter name="entryTitle" description="comments link label"/> + </xpath-ui-element> + <xpath-ui-element name="includeExternal" xpath="//a[contains(.//text(),'Include an')]" description="include an external already existing blog"></xpath-ui-element> + <xpath-ui-element name="edit" xpath="//a[@class='b_button b_small' and .//text()='Edit blog']" description="edit blog button"></xpath-ui-element> + <xpath-ui-element name="blogEntryDescriptionFrame" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Description']//div[@class='b_form_element']//iframe" description="description textarea of the blog"/> + <xpath-ui-element name="blogEntryContentFrame" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Content']//div[@class='b_form_element']//iframe" description="content textarea of the blog"/> + </pageset> + + <pageset name="podcast" description="podcast resource links"> + <xpath-ui-element name="create" xpath="//a[@class='b_button' and .//text()='Create your own episode']" description="create your own entries"></xpath-ui-element> + <xpath-ui-element name="addEpisode" xpath="//a[.//text()='Add episode']" description="Add episode button"/> + <!-- <xpath-ui-element name="editEpisode" xpath="//a[contains(.//text(),'Create') and ancestor::div[contains(@class,'o_podcast_episode')]//h5[contains(.//text(),'" + episodeTitle + "')]]" description="create or edit podcast episode"> + <parameter name="episodeTitle" description=""></parameter> + </xpath-ui-element>--> + <xpath-ui-element name="editEpisode" xpath="//a[contains(.//text(),'Create')]" description="create or edit episode"></xpath-ui-element> + <xpath-ui-element name="addComment" xpath="//a[@class='b_comments' and ancestor::div//h5[contains(.//text(),'" + entryTitle + "')]]" description="comments link"> + <parameter name="entryTitle" description="comments link label"/> + </xpath-ui-element> + <xpath-ui-element name="includeExternal" xpath="//a[contains(.//text(),'Include an')]" description="include an external already existing blog"></xpath-ui-element> + <xpath-ui-element name="edit" xpath="//a[@class='b_button b_small' and .//text()='Edit Podcast']" description="edit blog button"></xpath-ui-element> + </pageset> + + <pageset name="cpEditor" description="content package editor paths"> + <xpath-ui-element name="menuTreeLink" xpath="//div[@class='o_cpeditor_menu_tree']//a[./span/text()='" + link + "']" description="a page node link in the cp editor, containing the linkText" > + <parameter name="link" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="selectedTreeNodeExpanded" xpath="//div[@class='x-tree-node-el x-unselectable x-tree-node-expanded x-tree-selected']//a[./span/text()='" + link + "']" description="a selected expanded node link in the cp editor, containing the linkText" > + <parameter name="link" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="selectedTreeNodeLeaf" xpath="//div[@class='x-tree-node-el x-tree-node-leaf x-unselectable x-tree-selected']//a[./span/text()='" + link + "']" description="a selected leaf node link in the cp editor, containing the linkText" > + <parameter name="link" description="The text of the link"/> + </xpath-ui-element> + <xpath-ui-element name="addPage" xpath="//a[@class='o_cpeditor_new']" description="add page button"></xpath-ui-element> + <xpath-ui-element name="editPageProperties" xpath="//a[@class='o_cpeditor_edit']" description="edit page properties button"></xpath-ui-element> + <xpath-ui-element name="metadataTitleInput" xpath="//fieldset[//text()='Edit metadata']//input[@type='text']" description="metadata title input field"></xpath-ui-element> + <xpath-ui-element name="saveAndClose" xpath="//a[@class='b_button' and contains(.//text(),'Save and close')]" description="save and close button"></xpath-ui-element> + <xpath-ui-element name="copyPage" xpath="//a[@class='o_cpeditor_copy']" description="copy page button"></xpath-ui-element> + <xpath-ui-element name="importPage" xpath="//a[@class='o_cpeditor_import']" description="import page button"></xpath-ui-element> + <xpath-ui-element name="deletePage" xpath="//a[@class='o_cpeditor_delete']" description=" delete page button"></xpath-ui-element> + <xpath-ui-element name="preview" xpath="//a[@class='o_cpeditor_preview']" description="preview page button"></xpath-ui-element> + <xpath-ui-element name="dragAndDropSrcObject" xpath="//ul[@class='x-tree-node-ct']//a[contains(.//text(),'" + link + "')]" description="locator of object to be drag"> + <parameter name="link" description="link title"></parameter> + </xpath-ui-element> + <xpath-ui-element name="uploadFile" xpath="//a[contains(./span/text(),'Upload file')]" description="the upload file button"/> + <xpath-ui-element name="imageDescription" xpath="//input[@id='alt']" description="image description"/> + <xpath-ui-element name="insertImage" xpath="//input[@id='insert']" description="insert image button"/> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/olat-ui-map.xml b/src/test/profile/selenium/ui-map/olat-ui-map.xml new file mode 100644 index 0000000000000000000000000000000000000000..aa538b92ab5def7c1b0e91dd3f00f76e3cab4d28 --- /dev/null +++ b/src/test/profile/selenium/ui-map/olat-ui-map.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map> + <testcase-macro name="login"> + <call-macro name="adminlogin"/> + </testcase-macro> + <testcase-macro name="loginDeutsch"> + <call-macro name="adminloginDeutsch"/> + </testcase-macro> + + <include file="dmz-pageset.xml"/> + <include file="tabs-pageset.xml"/> + <include file="home-pageset.xml"/> + <include file="groups-pageset.xml"/> + <include file="group-pageset.xml"/> + <include file="groupManagement-pageset.xml"/> + <include file="learningResources-pageset.xml"/> + <include file="commons-pageset.xml"/> + <include file="course-pageset.xml"/> + <include file="courseEditor-pageset.xml"/> + <include file="testEditor-pageset.xml"/> + <include file="groupAdministration-pageset.xml"/> + <include file="userAdministration-pageset.xml"/> + <include file="qti-pageset.xml"/> + <include file="systemAdministration-pageset.xml"/> + <include file="projectBroker-pageset.xml"/> + <include file="infoMessage-pageset.xml"/> + <include file="portfolio-pageset.xml"/> + <include file="rightsManagement-pageset.xml" /> +</ui-map> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/portfolio-pageset.xml b/src/test/profile/selenium/ui-map/portfolio-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..7e0d907abcbdf81e110aae8c539cb4fce199be95 --- /dev/null +++ b/src/test/profile/selenium/ui-map/portfolio-pageset.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + + <pageset name="epCollectDialog" description="the collect dialog"> + + <xpath-ui-element xpath="//div[@class='b_wizard']//input" name="title" description="title field"/> + <xpath-ui-element xpath="//div[@class='b_wizard']//textarea" name="description" description="textarea field"/> + + <!-- mark: to use tag-component, leave away wizard-path --> + <xpath-ui-element xpath="//div[@class='b_wizard_steps_current']//div[@class and contains( concat( ' ', normalize-space(@class), ' ' ), ' holder ' )]//input[@class and contains( concat( ' ', normalize-space(@class), ' ' ), ' maininput ' )]" name="taginput" description="input field for tags"/> + <xpath-ui-element xpath="//div[@class='b_wizard_steps_current']//ul[@class='feed']/li[1]" name="taginputFeed" description="first element of the autocompletion feed"/> + <xpath-ui-element xpath="//div[@class='b_wizard_steps_current']//div[@class='b_form_selection_element']//input" name="copyrightCheckbox" description="checkbox for copyright"/> + + </pageset> + + <pageset name="epMenu" description="the left hand menu"> + <!-- todo: rh: fix as soon as epf is translated to EN --> + <xpath-ui-element name="ePortfolioArtefacts" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='My artefacts']" description="left navigation link 'eportfolio / my artefacts'"/> + <xpath-ui-element name="ePortfolioMyMaps" xpath="//div[contains(@class, 'o_home')]//div[@class='b_tree']//a[text()='My accumulative folders']" description="left navigation link 'eportfolio / my maps'"/> + </pageset> + + <pageset name="epArtefacts" description="artefact page"> + <xpath-ui-element xpath="//div[@class='b_artefact_count']" name="artefactCount" description="text containing artefact count"/> + <xpath-ui-element xpath="//div[@class='b_ep_add_artefact']//a" name="addArtefactLink" description="button to add artefact"/> + <xpath-ui-element xpath="//div[@class='b_ext_tooltip_wrapper']//li[1]//a" name="createTextArtefactLink" description="link to create a text-artefact"/> + <xpath-ui-element xpath="//div[@class='b_segments']//li[3]//a" name="artefactSearch" description="segmented view - artefact search"/> + </pageset> + + <pageset name="epArtefactSearch" description="search segment in artefact extension"> + <xpath-ui-element xpath="//div[@class='b_ep_filter b_float_left']//div[2]//div[2]/div/span[6]/a" name="textartefact" description="filter for text artefacts"/> + <xpath-ui-element xpath="//div[@class='b_subcl']/../../div[1]//a[contains(@class, 'b_delete_icon')]" name="deleteFirstArtefactLink" description="delete link of first left artefact"/> + <xpath-ui-element xpath="//div[@class='b_subcl']/../../div[1]//div[contains(@class, 'b_actions')]//a" name="firstArtefactChooseLink" description="link to choose an artefact"/> + <xpath-ui-element xpath="//div[contains(@class, 'b_ep_viewmode')]//input[@value='details']" name="viewModeDetails" description="radio for details mode"/> + </pageset> + + <pageset name="epMap" description="the map view"> + <xpath-ui-element xpath="//div[@class='b_ep_add_artefact']//a" name="addMapLink" description="button to add a map"/> + <xpath-ui-element xpath="//div[@class='b_ext_tooltip_wrapper']//li[1]//a" name="createDefaultMap" description="link to create a default map"/> + <xpath-ui-element xpath="//div[@class='b_ext_tooltip_wrapper']//li[2]//a" name="createMapFromTemplate" description="link to create a default map from a given template"/> + <xpath-ui-element xpath="//div[@id='o_addMapBox']//div/input" name="createMapTitle" description="input field for map title"/> + <xpath-ui-element xpath="//div[@id='o_addMapBox']//div/textarea" name="createMapDescription" description="input field for map description"/> + <xpath-ui-element xpath="//div[@id='o_addMapBox']//button" name="createMapSaveButton" description="save button"/> + + <xpath-ui-element xpath="//div[@class='b_pagination']//li[2]//a" name="firstPageLink" description="link in tab to first page"/> + <xpath-ui-element xpath="//div[@class='b_eportfolio_add_link']//a" name="addPageLink" description="link to add a page"/> + <xpath-ui-element xpath="//div[@class='b_eportfolio_page']//span[2]/a[contains(@class, 'b_eportfolio_add_link')]" name="addStructLink" description="link to add a structure"/> + <xpath-ui-element xpath="//div[@class='b_eportfolio_page']/div[1]//span[1]/a[contains(@class, 'b_eportfolio_add_link')]" name="attachArtefactToPageLink" description="link to add a artefact"/> + <xpath-ui-element xpath="//div[@class='b_eportfolio_structure'][1]//span[1]/a[contains(@class, 'b_eportfolio_add_link')]" name="attachArtefactToStructLink" description="link to add a artefact"/> + + <xpath-ui-element name="openMap" xpath="//ul[@class='b_eportfolio_maps']//li/h4[contains(text(), '" + titleOfMap + "')]/..//span[1]/a" description="get link to a map"> + <parameter name="titleOfMap" description="the title of the map"/> + </xpath-ui-element> + + <xpath-ui-element name="shareMap" xpath="//ul[@class='b_eportfolio_maps']//li/h4[contains(text(), '" + titleOfMap + "')]/..//span[2]/a" description="get link to share a map"> + <parameter name="titleOfMap" description="the title of the map"/> + </xpath-ui-element> + + <xpath-ui-element xpath="//div[@class='b_eportfolio']//span[text()='Open Editor']/.." name="openEditor" description="open the map editor"/> + <xpath-ui-element xpath="//div[@class='b_eportfolio']//span[text()='Close Editor']/.." name="closeEditor" description="close the map editor"/> + </pageset> + + <pageset name="epMapEditor" description="the map editor"> + <xpath-ui-element xpath="//div[contains(@class, 'o_ep_struct_editor')]//input[@type='text']" name="elTitle" description="title input element"/> + <xpath-ui-element xpath="//div[contains(@class, 'o_ep_struct_editor')]//div/textarea" name="elDescription" description="description for this element"/> + <xpath-ui-element xpath="//div[contains(@class, 'o_ep_struct_editor')]//button" name="saveEditor" description="save form"/> + <xpath-ui-element xpath="//a[contains(@class, 'b_delete_icon')]" name="deleteButton" description="delete active element"/> + </pageset> + + <pageset name="epShare" description="the map share view"> + <xpath-ui-element xpath="//div[contains(@id, 'o_shareBox' )]//form//div[2]//a" name="createRule" description="create rule button"/> + <xpath-ui-element xpath="//div[@class and contains( concat( ' ', normalize-space(@class), ' ' ), ' holder ' )]//input[@class and contains( concat( ' ', normalize-space(@class), ' ' ), ' maininput ' )]" name="nameInput" description="input field for usernames"/> + <xpath-ui-element xpath="//ul[@class='feed']/li[1]" name="nameInputSelect" description="select entry from input field for usernames"/> + <xpath-ui-element xpath="//div[@class='b_button_group']//button" name="saveShare" description="save form"/> + </pageset> + + +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/projectBroker-pageset.xml b/src/test/profile/selenium/ui-map/projectBroker-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..f7548f5a6aef7afb17cdc183842b4dfe48984e79 --- /dev/null +++ b/src/test/profile/selenium/ui-map/projectBroker-pageset.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> +<!-- aka Topic assignment --> + <pageset name="projectBroker" description="project broker links"> + <xpath-ui-element name="createTopic" xpath="//a[.//text()='Create Topic']" description="create topic button"/> + <!-- use commons::flexiForm_labeledTextInput for registration and due date starting dates --> + <xpath-ui-element name="registrationDeadline" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Deadline'][1]//div[@class='b_form_element']//input[@type='text']" description="registration deadline input field"></xpath-ui-element> + <xpath-ui-element name="dueDeadline" xpath="//div[@class='b_form_element_wrapper b_clearfix'][descendant::text()='Deadline'][2]//div[@class='b_form_element']//input[@type='text']" description="due date deadline"></xpath-ui-element> + <!-- <xpath-ui-element name="deleteTopic" xpath="//a[.//text()='Delete Topic']" description="detele topic button"></xpath-ui-element> asa unused --> + + <xpath-ui-element name="doLimitVacancies" xpath="//input[@type='checkbox' and @name='detailsform.max.candidates.label']" description="do you want to limit the vacancies - checkbox"/> + <xpath-ui-element name="vacanciesNumber" xpath="//input[@type='text' and @size='3']" description="number of vacancies"/> + + <!-- topic table --> + <xpath-ui-element name="topicLink" xpath="//form//table//a[descendant::text()='" + nameOfTopic + "']" description="topic link in topic table"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="selectTopic" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td/a[descendant::text()='Select']" description="select topic with the given name"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="hasVacancies" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Vacancies']" description="topic has vacancies"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + + <xpath-ui-element name="filled" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Filled']" description="topic is filled"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="temporaryRegistration" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Temporary registration']" description="Temporary registration"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="isRegistered" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Positive registration']" description="Positive registration"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="checkParticipants" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Check participants']" description="Check participants"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + <xpath-ui-element name="participantsAccepted" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td[descendant::text()='Participants accepted']" description="Participants accepted"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + + <xpath-ui-element name="deselectTopic" xpath="//td[@class='b_align_normal b_first_child']//a[descendant::text()='" + nameOfTopic + "']/../..//td/a[descendant::text()='Deselect']" description="deselect topic with the given name"> + <parameter name="nameOfTopic" description="the name of the topic"/> + </xpath-ui-element> + + <pageset name="folder" description="folder specifics"> + <xpath-ui-element name="folderTab" xpath="//a[descendant::text()='Folder']" description="folder tab"/> + <xpath-ui-element name="dropboxDiv" xpath="//div[@class='o_course_run_dropbox']" description="dropbox div"/> + <xpath-ui-element name="dropBoxFolderLink" xpath="//div[@class='o_course_run_dropbox']//a[text()='" + folderName + "']" description="drop box folder link"> + <parameter name="folderName" description="user name"/> + </xpath-ui-element> + <xpath-ui-element name="uploadFile" xpath="//a[.//text()='Upload file']" description="Link to upload a file"/> + <xpath-ui-element name="uploadFileInOverlay" xpath="//div[@class='b_window_content']//a[.//text()='Upload file']" description="the upload file in an overlay"/> + <xpath-ui-element name="returnboxDiv" xpath="//div[@class='o_course_run_returnbox']" description="returnbox div"/> + <xpath-ui-element name="returnboxFolderCheckbox" xpath="//div[@class='o_course_run_returnbox']//input[@value='" + folderName + "']" description="folder in return box"> + <parameter name="folderName" description="The name of the folder"></parameter> + </xpath-ui-element> + <xpath-ui-element name="returnBoxFolderLink" xpath="//div[@class='o_course_run_returnbox']//a[text()='" + folderName + "']" description="return box folder link"> + <parameter name="folderName" description="user name"/> + </xpath-ui-element> + </pageset> + + <pageset name="administrationOfParticipants" description="Administration of participants tab"> + <xpath-ui-element name="adminTab" xpath="//div[@class='b_tabbedpane_tabs']//a[contains(.//text(),'Administration')]" description="Administration of participants tab link"/> + <pageset name="candidates" description="candidates table"> + <xpath-ui-element name="checkUser" xpath="//fieldset[legend[contains(.//text(),'Candidates')]]//tr[./td//text()='" + userName + "']//input[@type='checkbox']" description="check candidate"> + <parameter name="userName" description="user name"/> + </xpath-ui-element> + <xpath-ui-element name="moveToParticipants" xpath="//input[@name='move.user.waitinglist']" description="Transfer as participant"/> + </pageset> + <pageset name="participants" description="participants table"> + <xpath-ui-element name="checkUser" xpath="//fieldset[legend[contains(.//text(),'Participants accepted')]]//tr[./td//text()='" + userName + "']//input[@type='checkbox']" description="check participant"> + <parameter name="userName" description="userName"/> + </xpath-ui-element> + </pageset> + <pageset name="authors" description="authors table"> + <xpath-ui-element name="checkUser" xpath="//fieldset[legend[contains(.//text(),'Topic authors')]]//tr[./td//text()='" + userName + "']//input[@type='checkbox']" description="check author"> + <parameter name="userName" description="userName"/> + </xpath-ui-element> + </pageset> + </pageset> + </pageset> + + +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/qti-pageset.xml b/src/test/profile/selenium/ui-map/qti-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..f925023d2525b5694144021a084d9c8b40c88768 --- /dev/null +++ b/src/test/profile/selenium/ui-map/qti-pageset.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="qti" description="Test run links"> + <xpath-ui-element name="showHideResults" xpath="//div[@class='o_course_run_scoreinfo']/..//a[@class='b_button' and descendant::text()='" + text + "']" description="Show/Hide results button on test start page"> + <parameter name="text" description="the text of button"> + <defaultValue value="Show results" /> + <defaultValue value="Hide results" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="menuItem" xpath="//div[@class='o_qti_menu_item']//a[@title='" + titleOfItem + "']" description="Click on qti menu item with the given title"> + <parameter name="titleOfItem" description="the title of the qti menu item"> + <defaultValue value="Single Choice" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="saveAnswer" xpath="//input[@value='Save answer ']" description="Click 'Save answer ' button"/> + <xpath-ui-element name="finishTest" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Finish test ')]" description="Click 'Finish test' button"/> + <xpath-ui-element name="cancelTest" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Cancel test ')]" description="button cancel test"/> + <xpath-ui-element name="suspendTest" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Suspend test ')]" description="button suspend test"/> + <xpath-ui-element name="achievedScore" xpath="//td[contains(descendant::text(), 'Achieved score')]/../td[3]/text()" description="find the score xpath - at the end of test run - before close test"/> + <xpath-ui-element name="closeTest" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Close')]" description="Click 'Close' button in test"/> + <xpath-ui-element name="yourScore" xpath="//td[contains(descendant::text(), 'Your score: ')]/../td[2]/text()" description="find the score xpath - test course node selected"/> + <xpath-ui-element name="yourStatus" xpath="//td[contains(descendant::text(), 'Status: ')]/../td[2]/span/text()" description="find the status xpath - test course node selected"/> + <xpath-ui-element name="commentFromTutor" xpath="//td[contains(descendant::text(), 'Comment')]/../td[2]/text()" description="find the status xpath - test course node selected"/> + + <xpath-ui-element name="finishQuestionnaire" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Finish questionnaire')]" description="Click 'Finish questionnaire' button"/> + <xpath-ui-element name="cancelQuestionnaire" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Cancel questionnaire')]" description="button cancel questionnaire"/> + <xpath-ui-element name="suspendQuestionnaire" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Suspend questionnaire ')]" description="button suspend questionnaire"/> + <!-- <xpath-ui-element name="closeQuestionnaire" xpath="//div[@id='o_qti_run']//a[@class='b_button'][contains(descendant::text(), 'Close')]" description="Click 'Close' button in questionnaire"/> asa unused --> + <xpath-ui-element name="testItemFormElement" xpath="//div[@class='o_qti_item_choice']/div[@class='o_qti_item_choice_option']/div[@class='o_qti_item_choice_option_value' and .//text()='" + text + "']/../div[@class='o_qti_item_choice_option_input']/input" description="select the form element with the given text"> + <parameter name="text" description="the text of the form element"> + <defaultValue value="Antwort 1" /> + </parameter> + </xpath-ui-element> + <link-ui-element name="next" link="Next" description="The next link"/> + + <xpath-ui-element name="testKprimItemFormElementPlus" xpath="//table[@class='o_qti_item_kprim']//tr//td[descendant::text()='" + text + "']/..//td[1]/input[@class='b_radio']" + description="the text of the kprim item plus"> + <parameter name="text" description="the text of the kprim element"> + <defaultValue value="Antwort 1" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="testKprimItemFormElementMinus" xpath="//table[@class='o_qti_item_kprim']//tr//td[descendant::text()='" + text + "']/..//td[2]/input[@class='b_radio']" + description="the text of the kprim item minus"> + <parameter name="text" description="the text of the kprim element"> + <defaultValue value="Antwort 1" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="testGapItemFormElement" xpath="//div[@class='o_qti_item']//span[@class='o_qti_item_mattext' and descendant::text()='" + text + "']/following-sibling::input[1]" description="type in gap"> + <parameter name="text" description="the text that precedes the gap"> + <defaultValue value="abc" /> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="questionnaireEssayTextArea" xpath="//div[@class='o_qti_item']//textarea" description="the textarea for the essay"/> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/gen_olat-ui-map.xsl b/src/test/profile/selenium/ui-map/resources/gen_olat-ui-map.xsl new file mode 100644 index 0000000000000000000000000000000000000000..1e43cf15c6cc07bae645f5d0f292706898649c7d --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/gen_olat-ui-map.xsl @@ -0,0 +1,476 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:output method="text"/> + + <xsl:template match="ui-map"> + <xsl:text> +// +// OLAT-UI-MAP.JS +// ============== +// This file contains the mappings of xpaths/links to selenium-understood javascript which can then +// be used in Selenium IDE and Selenium RC for testing. +// +// +// Note: This file is generatd using the ui-map/gen_olat-ui-map.xsl with the actual mappings stored in +// --> ui-map/olat-ui-map.xml +// + + +// INSTALL NOTE FOR SELENIUM IDE +// ----------------------------- +// +// add the following line to Selenium IDE>Options>Options...>Selenium Core extensions (user-extensions.js): +// +// chrome://selenium-ide/content/ui-element.js, C:\eclipse\workspace\seleniumtesting\src\olat-ui-map.js + + +var myMap = new UIMap(); + +</xsl:text> + <xsl:apply-templates select="pageset"/> + </xsl:template> + + +<!-- + + +// +// +// ================== +// The main OLAT tabs +// ================== +// +// +myMap.addPageset({ + name: 'tabs' + , description: 'main OLAT tabs' + , pathRegexp: '.*' +}); + + --> + <xsl:template match="pageset"> + <xsl:if test="count(ancestor::pageset)=0"> + <xsl:if test="count(@description)=0 or @description=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>you must specify a description! Pageset=</xsl:text> + <xsl:value-of select="@name"/> + </xsl:message> + </xsl:if> + <xsl:text> +// +// +// ====== +// PAGESET: </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> +// ====== +// +// +myMap.addPageset({ + name: '</xsl:text><xsl:value-of select="@name"/><xsl:text>' +</xsl:text> + <xsl:if test="@description"> + <xsl:text> , description: "</xsl:text> + <xsl:value-of select="@description"/> + <xsl:text>" +</xsl:text> + </xsl:if> + <xsl:text> , pathRegexp: '.*' +}); + +</xsl:text> + + </xsl:if> + <xsl:apply-templates select="pageset"/> + <xsl:apply-templates select="xpath-ui-element"/> + <xsl:apply-templates select="link-ui-element"/> + <xsl:apply-templates select="var-link-ui-element"/> + </xsl:template> + +<!-- + +// ADMINISTRATION +myMap.addElement('tabs', { + name: 'administration' + , description: 'main tab "Administration"' + , xpath: "//a[span/text()='Administration']" + , testcase1: { + xhtml: '<a expected-result="1"><span>Administration</span></a>' + } +}); + + --> +<!-- + +// CLOSE AN OPENED COURSE +myMap.addElement('tabs', { + name: 'closeCourse' + , description: 'close a course' + , args: [ + { + name: 'nameOfCourse' + , description: 'the name of the course' + , defaultValues: [ 'Demo Course', 'Demo course wiki' ] + } + ] + , getLocator: function(args) { + var nameOfCourse = args['nameOfCourse']; + return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + } +}); + + + --> + <xsl:template match="xpath-ui-element"> + <xsl:variable name="name"> + <xsl:for-each select="ancestor::pageset[count(ancestor::pageset)!=0]"> + <xsl:value-of select="@name"/> + <xsl:text>_</xsl:text> + </xsl:for-each> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:if test="count(@description)=0 or @description=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>you must specify a description! Element=</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>::</xsl:text> + <xsl:value-of select="$name"/> + </xsl:message> + </xsl:if> + <!-- a newline first --> + <xsl:text> +</xsl:text> + + <!-- // USERNAME input field --> + <xsl:if test="@description"> + <xsl:text>// </xsl:text> + <xsl:value-of select="@description"/> + <xsl:text> +</xsl:text> + </xsl:if> + + <!-- myMap.addElement('dialog', { --> + <xsl:text>myMap.addElement('</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>', { +</xsl:text> + + <!-- name: 'OK' --> + <xsl:text> name: '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' +</xsl:text> + + <!-- , description: 'OK Button in Dialog Popup Window' --> + <xsl:if test="@description"> + <xsl:text> , description: "</xsl:text> + <xsl:value-of select="@description"/> + <xsl:text>" +</xsl:text> + </xsl:if> + + <xsl:choose> + <xsl:when test="count(parameter)>0"> +<!-- + , args: [ + { + name: 'nameOfCourse' + , description: 'the name of the course' + , defaultValues: [ 'Demo Course', 'Demo course wiki' ] + } + ] + , getLocator: function(args) { + var nameOfCourse = args['nameOfCourse']; + return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + } + --> + <xsl:text> , args: [ + {</xsl:text> + <xsl:for-each select="parameter"> + <xsl:text> + name: '</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>' + , defaultValues: [ </xsl:text> + <xsl:if test="count(defaultValue)=0"> + <xsl:text> "Foo", "Bar" </xsl:text> + </xsl:if> + <xsl:for-each select="defaultValue"> + <xsl:if test="position()!=1"> + <xsl:text>, </xsl:text> + </xsl:if> + <xsl:text>"</xsl:text> + <xsl:value-of select="@value"/> + <xsl:text>"</xsl:text> + </xsl:for-each> + <xsl:text> ] +</xsl:text> + <xsl:if test="@description"> + <xsl:text> , description: "</xsl:text> + <xsl:value-of select="@description"/> + <xsl:text>" +</xsl:text> + </xsl:if> + </xsl:for-each> + <xsl:text> } + ] + , getLocator: function(args) { +</xsl:text> + <!-- var nameOfCourse = args['nameOfCourse']; + --> + <xsl:for-each select="parameter"> + <xsl:text> var </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> = args['</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>']; +</xsl:text> + </xsl:for-each> + + <!-- return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + --> + <xsl:text> return "</xsl:text> + <xsl:value-of select="@xpath"/> + <xsl:text>"; + } +}); +</xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- , xpath: '//div[contains(@class, "x-window")]//button[text()="OK"]' --> + <xsl:text> , xpath: "</xsl:text> + <xsl:value-of select="@xpath"/> + <xsl:text>" +}); +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + + +<!-- + +// ADMINISTRATION +myMap.addElement('tabs', { + name: 'administration' + , description: 'main tab "Administration"' + , xpath: "//a[span/text()='Administration']" + , testcase1: { + xhtml: '<a expected-result="1"><span>Administration</span></a>' + } +}); + + --> + <xsl:template match="link-ui-element"> + <xsl:variable name="name"> + <xsl:for-each select="ancestor::pageset[count(ancestor::pageset)!=0]"> + <xsl:value-of select="@name"/> + <xsl:text>_</xsl:text> + </xsl:for-each> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:if test="count(@description)=0 or @description=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>you must specify a description! Element=</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>::</xsl:text> + <xsl:value-of select="$name"/> + </xsl:message> + </xsl:if> + <!-- a newline first --> + <xsl:text> +</xsl:text> + + <!-- // USERNAME input field --> + <xsl:if test="@description"> + <xsl:text>// </xsl:text> + <xsl:value-of select="@description"/> + <xsl:text> +</xsl:text> + </xsl:if> + + <!-- myMap.addElement('dialog', { --> + <xsl:text>myMap.addElement('</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>', { +</xsl:text> + + <!-- name: 'OK' --> + <xsl:text> name: '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' +</xsl:text> + + <!-- , description: 'OK Button in Dialog Popup Window' --> + <xsl:if test="@description"> + <xsl:text> , description: "</xsl:text> + <xsl:value-of select="@description"/> + <xsl:text>" +</xsl:text> + </xsl:if> + + <!-- , xpath: '//a[.//text()="Close detailed view"]' --> + <xsl:text> , xpath: "//a[.//text()='</xsl:text> + <xsl:value-of select="@link"/> + <xsl:text>']" +}); +</xsl:text> + </xsl:template> + + +<!-- + +// CLOSE AN OPENED COURSE +myMap.addElement('tabs', { + name: 'closeCourse' + , description: 'close a course' + , args: [ + { + name: 'nameOfCourse' + , description: 'the name of the course' + , defaultValues: [ 'Demo Course', 'Demo course wiki' ] + } + ] + , getLocator: function(args) { + var nameOfCourse = args['nameOfCourse']; + return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + } +}); + + + --> + <xsl:template match="var-link-ui-element"> + <xsl:variable name="name"> + <xsl:for-each select="ancestor::pageset[count(ancestor::pageset)!=0]"> + <xsl:value-of select="@name"/> + <xsl:text>_</xsl:text> + </xsl:for-each> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:if test="count(@description)=0 or @description=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>you must specify a description! Element=</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>::</xsl:text> + <xsl:value-of select="$name"/> + </xsl:message> + </xsl:if> + <!-- a newline first --> + <xsl:text> +</xsl:text> + + <!-- // USERNAME input field --> + <xsl:if test="@description"> + <xsl:text>// </xsl:text> + <xsl:value-of select="@description"/> + <xsl:text> +</xsl:text> + </xsl:if> + + <!-- myMap.addElement('dialog', { --> + <xsl:text>myMap.addElement('</xsl:text> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>', { +</xsl:text> + + <!-- name: 'OK' --> + <xsl:text> name: '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' +</xsl:text> + + <!-- , description: 'OK Button in Dialog Popup Window' --> + <xsl:if test="@description"> + <xsl:text> , description: "</xsl:text> + <xsl:value-of select="@description"/> + <xsl:text>" +</xsl:text> + </xsl:if> + +<!-- + , args: [ + { + name: 'nameOfCourse' + , description: 'the name of the course' + , defaultValues: [ 'Demo Course', 'Demo course wiki' ] + } + ] + , getLocator: function(args) { + var nameOfCourse = args['nameOfCourse']; + return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + } + --> + <xsl:text> , args: [ + {</xsl:text> + <xsl:text> + name: '</xsl:text> + <xsl:value-of select="@linkparam"/> + <xsl:text>' + , defaultValues: [ "none" ] + , description: "the link parameter" + } + ] + , getLocator: function(args) { +</xsl:text> + <!-- var nameOfCourse = args['nameOfCourse']; + --> + <xsl:text> var linkparam = args['</xsl:text> + <xsl:value-of select="@linkparam"/> + <xsl:text>']; +</xsl:text> + + <!-- return "//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']"; + --> + <xsl:text> return "link="+linkparam; + } +}); +</xsl:text> + </xsl:template> + + +</xsl:stylesheet> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/gen_selenium-map-tests.xsl b/src/test/profile/selenium/ui-map/resources/gen_selenium-map-tests.xsl new file mode 100644 index 0000000000000000000000000000000000000000..6910acc061b3bffef034af446a4f5e7f8fb434b3 --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/gen_selenium-map-tests.xsl @@ -0,0 +1,694 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:param name="mode"/> + <xsl:output method="text"/> + + <xsl:template match="ui-map"> + <xsl:choose> + <xsl:when test="$mode='fast'"> + <xsl:call-template name="fastmode"/> + </xsl:when> + <xsl:when test="$mode='slow'"> + <xsl:apply-templates select="pageset"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:text> + +-------------------------------- +Error in seleniumtests/build.xml +-------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>Must set parameter $mode to 'slow' or 'fast' when calling gen_selenium-map-tests.xsl! Shame on you!</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="fastmode"> + <xsl:variable name="testclassname" select="'GenerateFastdOlatMapTest'"/> + <xsl:variable name="testmethodname" select="'generatedOlatMapTest'"/> + <xsl:variable name="filename" select="concat($testclassname, '.java')"/> + <xsl:result-document href="{$filename}"> + <xsl:text> +package org.olat.test.generated; + +import org.olat.test.util.selenium.OlatLoginHelper; +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +@Test(groups = {"generated"}) +/** + * This test was generated from the olat-ui-map.xml by gen_selenium-map-tests.xsl. + * + * This variant is the result of mode=fast in which everything happens within the + * same browser to speed up things considerably. every testcase does a logout at the + * end. the downside of this approach is, when something fails, it stops the test + * and you don't see any results of the subsequent tests. + * + * Therefore you probably want to run in mode=slow until everything is fixed, + * then you want to switch to mode=fast until something breaks again. + * + * Happy Selenium-Map-Testing, Mate! + **/ +public class </xsl:text> + <xsl:value-of select="$testclassname"/> + <xsl:text> extends BaseSeleneseTestCase { + + @Test + public void test_</xsl:text> + <xsl:value-of select="$testmethodname"/> + <xsl:text>() throws Exception { +</xsl:text> + + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSeleniumAndLogin(); + + <xsl:apply-templates select="pageset"/> + <xsl:text> + } + +} +</xsl:text> + + </xsl:result-document> + </xsl:template> + + <xsl:template match="pageset"> + <xsl:apply-templates select="pageset"/> + <xsl:apply-templates select="xpath-ui-element"/> + <xsl:apply-templates select="link-ui-element"/> + <xsl:apply-templates select="var-link-ui-element"/> + </xsl:template> + + <xsl:template match="xpath-ui-element"> + <xsl:call-template name="ui-element"/> + </xsl:template> + + <xsl:template match="link-ui-element"> + <xsl:call-template name="ui-element"/> + </xsl:template> + + <xsl:template match="var-link-ui-element"> + <xsl:call-template name="ui-element"/> + </xsl:template> + + <!-- this template creates the actual test class for the ui-element at which we're at --> + <xsl:template name="ui-element"> + <xsl:variable name="fullUiElementName"> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>_</xsl:text> + <xsl:for-each select="ancestor::pageset[count(ancestor::pageset)!=0]"> + <xsl:value-of select="@name"/> + <xsl:text>_</xsl:text> + </xsl:for-each> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:variable name="fullUiElementName_SeleniumSyntax"> + <xsl:value-of select="ancestor-or-self::pageset[count(ancestor::pageset)=0]/@name"/> + <xsl:text>::</xsl:text> + <xsl:for-each select="ancestor::pageset[count(ancestor::pageset)!=0]"> + <xsl:value-of select="@name"/> + <xsl:text>_</xsl:text> + </xsl:for-each> + <xsl:value-of select="@name"/> + </xsl:variable> + + <xsl:variable name="defaultTestCaseDef" select="../default-testcase"/> + + <xsl:choose> + <!-- this ui-element explicitly has testcase="" set, meaning that we dont generate a testcase here --> + <xsl:when test="@testcase and @testcase=''"> + <!-- nothing --> + </xsl:when> + + <!-- this ui-element has its own testcase defined, so use this one --> + <xsl:when test="@testcase and @testcase!=''"> + <xsl:call-template name="gen-testcase"> + <xsl:with-param name="testcase" select="@testcase"/> + <xsl:with-param name="fullUiElementName" select="$fullUiElementName"/> + </xsl:call-template> + </xsl:when> + + <!-- this ui-element doesn't have its own testcase defined. take the nearest <default-testcase/> --> + <xsl:when test="count($defaultTestCaseDef)=1"> + <xsl:if test="not($defaultTestCaseDef/@testcase) or $defaultTestCaseDef/@testcase='' or not($defaultTestCaseDef/@final-command) or $defaultTestCaseDef/@final-command=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>a default-testcase is not properly configured (testcase or final-command missing). </xsl:text> + <xsl:value-of select="$fullUiElementName"/> + </xsl:message> + </xsl:if> + + <xsl:choose> + <xsl:when test="contains($defaultTestCaseDef/@final-command, '(') and contains($defaultTestCaseDef/@final-command, ')')"> + <!-- special case: the final-command contains (foobar) --> + <!-- convert that into: final-command(ui-elemen,foobar) --> + <xsl:variable name="rawFinalCommand" select="substring-before($defaultTestCaseDef/@final-command, '(')"/> + <xsl:variable name="secondFuncParam" select="substring-before(substring-after($defaultTestCaseDef/@final-command, '('), ')')"/> + <xsl:if test="$secondFuncParam=''"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>a default-testcase is not properly configured (final-command must not contain () but no params. either (param) or without brackets in the first place). </xsl:text> + <xsl:value-of select="$fullUiElementName"/> + </xsl:message> + </xsl:if> + <xsl:call-template name="gen-testcase"> + <xsl:with-param name="testcase" select="concat($defaultTestCaseDef/@testcase, '/', $rawFinalCommand, '(', $fullUiElementName_SeleniumSyntax,',',$secondFuncParam,')')"/> + <xsl:with-param name="fullUiElementName" select="$fullUiElementName"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- this is the normal case: the final-command does not contain () --> + <xsl:call-template name="gen-testcase"> + <xsl:with-param name="testcase" select="concat($defaultTestCaseDef/@testcase, '/', $defaultTestCaseDef/@final-command, '(', $fullUiElementName_SeleniumSyntax,')')"/> + <xsl:with-param name="fullUiElementName" select="$fullUiElementName"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + + </xsl:when> + + <xsl:otherwise> + <!-- nothing else yet... allow ui-elements without testcase for now... we might want to restrict this and issue a warn here later --> + + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="gen-testcase"> + <xsl:param name="testcase"/> + <xsl:param name="fullUiElementName"/> + + <xsl:text> + +// Testcase: </xsl:text> + <xsl:value-of select="$testcase"/> + <xsl:text> +// FullUiElementName: </xsl:text> + <xsl:value-of select="$fullUiElementName"/> + + <xsl:variable name="testclassname" select="concat('GeneratedOlatMapTest_', $fullUiElementName)"/> + <xsl:variable name="testmethodname" select="concat('generatedOlatMapTest_', $fullUiElementName)"/> + <xsl:variable name="filename" select="concat($testclassname, '.java')"/> + + <xsl:choose> + <xsl:when test="$mode='slow'"> + <xsl:result-document href="{$filename}"> + <xsl:text> +package org.olat.test.generated; + +import org.olat.test.util.selenium.BaseSeleneseTestCase; +import org.olat.test.util.setup.SetupType; +import org.olat.test.util.setup.context.Context; +import org.testng.annotations.Test; + +@Test(groups = {"generated"}) +/** + * This test was generated from the olat-ui-map.xml by gen_selenium-map-tests.xsl. + * + * It's testing the ui-element: </xsl:text><xsl:value-of select="$fullUiElementName"/><xsl:text>. + * + * The testcase is generated from this string: </xsl:text><xsl:value-of select="$testcase"/><xsl:text>. + **/ +public class </xsl:text> + <xsl:value-of select="$testclassname"/> + <xsl:text> extends BaseSeleneseTestCase { + + @Test + public void test_</xsl:text> + <xsl:value-of select="$testmethodname"/> + <xsl:text>() throws Exception { +</xsl:text> + <xsl:call-template name="code-for-expression"> + <xsl:with-param name="expr" select="$testcase"/> + </xsl:call-template> + <xsl:text> + } + +} +</xsl:text> + </xsl:result-document> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="code-for-expression"> + <xsl:with-param name="expr" select="$testcase"/> + </xsl:call-template> + + <xsl:text> + + // Cleanup at the end of an individual link-test + if (selenium.isElementPresent("ui=tabs::logOut()")) { + System.out.println("[CLEANUP] Clicking logOut now..."); + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + System.out.println("[CLEANUP] Done with logOut."); + } else if (!"OLAT - Online Learning And Training".equals(selenium.getTitle())) { + System.out.println("[CLEANUP] Can't click logOut, there is no logOut link available..."); + // emergency + System.out.println("[CLEANUP] EMERGENCY HERE: opening the original url again: "+context.getStandardAdminOlatLoginInfos().getFullOlatServerUrl()); + selenium.open(context.getStandardAdminOlatLoginInfos().getFullOlatServerUrl()); + System.out.println("[CLEANUP] Did that, now let's wait a few sec... like 5 or so should be fine"); + Thread.sleep(5000); + } + System.out.println("[CLEANUP] Title now: "+selenium.getTitle()); + assertEquals("We're now in DMZ - did the logOut now work?", "OLAT - Online Learning And Training", selenium.getTitle()); + // Done with Cleanup + +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="code-for-expression"> + <xsl:param name="expr"/> + + <xsl:choose> + <xsl:when test="contains($expr, '/')"> + <xsl:variable name="step" select="substring-before($expr, '/')"/> + <xsl:call-template name="code-for-expression"> + <xsl:with-param name="expr" select="$step"/> + </xsl:call-template> + <xsl:variable name="remainder" select="substring-after($expr, '/')"/> + <xsl:call-template name="code-for-expression"> + <xsl:with-param name="expr" select="$remainder"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$expr=''"> + <!-- do nothing --> + </xsl:when> + + <xsl:otherwise> + <xsl:choose> + <xsl:when test="(not(contains($expr, '(')) and contains($expr, '::'))"> + <!-- then it's a selenium clickAndWait command --> + <xsl:text> + // Step-Start: selenium.clickAndWait("</xsl:text> + <xsl:value-of select="$expr"/> + <xsl:text>()"); +</xsl:text> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="$expr"/> + </xsl:call-template> + <xsl:text>"); + selenium.waitForPageToLoad("30000"); + // Step-End +</xsl:text> + </xsl:when> + <xsl:when test="(contains(substring-before($expr, '('), '::'))"> + <!-- then it's a selenium clickAndWait command --> + <xsl:text> + // Step-Start: selenium.clickAndWait("</xsl:text> + <xsl:value-of select="$expr"/> + <xsl:text>"); +</xsl:text> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="$expr"/> + </xsl:call-template> + <xsl:text>"); + selenium.waitForPageToLoad("30000"); + // Step-End +</xsl:text> + </xsl:when> + <xsl:when test="contains($expr, '(')"> + <!-- then it's a direct selenium command --> + <xsl:text> + // Step-Start: selenium.</xsl:text> + <xsl:value-of select="$expr"/> + <xsl:text> +</xsl:text> + <xsl:call-template name="expandDirectSeleniumCommand"> + <xsl:with-param name="expr" select="$expr"/> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text> // Step-End +</xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- then it's a macro call --> + <xsl:call-template name="resolveMacro"> + <xsl:with-param name="macro" select="$expr"/> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="expandDirectSeleniumCommand"> + <xsl:param name="expr"/> + <xsl:param name="node"/> + <xsl:choose> + <xsl:when test="starts-with($expr, 'type(') and ends-with($expr, ')')"> + <!-- type(dmz::username,foo) --> + <!-- selenium.type("ui=dmz::username()", username); --> + <xsl:text> selenium.type("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="substring-before(substring-after($expr, 'type('),',')"/> + </xsl:call-template> + <xsl:text>", "</xsl:text> + <xsl:value-of select="substring-before(substring-after($expr, ','),')')"/> + <xsl:text>"); +</xsl:text> + </xsl:when> + <xsl:when test="starts-with($expr, 'click(') and ends-with($expr, ')')"> + <!-- clickAndWait(dmz::login) --> + <!-- selenium.click("ui=tabs::learningResources()"); --> + <!-- selenium.waitForPageToLoad("30000"); --> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="substring-before(substring-after($expr, 'click('),')')"/> + </xsl:call-template> + <xsl:text>"); +</xsl:text> + </xsl:when> + <xsl:when test="starts-with($expr, 'check(') and ends-with($expr, ')')"> + <!-- clickAndWait(dmz::login) --> + <!-- selenium.click("ui=tabs::learningResources()"); --> + <!-- selenium.waitForPageToLoad("30000"); --> + <xsl:text> selenium.check("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="substring-before(substring-after($expr, 'check('),')')"/> + </xsl:call-template> + <xsl:text>"); +</xsl:text> + </xsl:when> + <xsl:when test="starts-with($expr, 'clickAndWait(') and ends-with($expr, ')')"> + <!-- clickAndWait(dmz::login) --> + <!-- selenium.click("ui=tabs::learningResources()"); --> + <!-- selenium.waitForPageToLoad("30000"); --> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="substring-before(substring-after($expr, 'clickAndWait('),')')"/> + </xsl:call-template> + <xsl:text>"); + selenium.waitForPageToLoad("30000"); +</xsl:text> + </xsl:when> + <xsl:when test="starts-with($expr, 'select(') and ends-with($expr, ')')"> + <!-- select(dmz::language,English) --> + <!-- selenium.select("ui=dmz::language()", "English"); --> + <xsl:text> selenium.select("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="substring-before(substring-after($expr, 'select('),',')"/> + </xsl:call-template> + <xsl:text>", "</xsl:text> + <xsl:value-of select="substring-before(substring-after($expr, ','),')')"/> + <xsl:text>"); +</xsl:text> + </xsl:when> + + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>Selenium-Shortcut not defined in gen_selenium-map.test.xsl: </xsl:text> + <xsl:value-of select="$expr"/> + <xsl:text> in element=</xsl:text> + <xsl:value-of select="name($node)"/> + <xsl:for-each select="$node/@*"> + <xsl:text> attribute: </xsl:text> + <xsl:value-of select="name()"/> + <xsl:text>=</xsl:text> + <xsl:value-of select="."/> + </xsl:for-each> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="resolveMacro"> + <xsl:param name="macro"/> + <xsl:param name="node"/> + + <xsl:text> + // Step-Start: MACRO: </xsl:text> + <xsl:value-of select="$macro"/> + + <xsl:choose> + <xsl:when test="$macro='adminlogin'"> + <xsl:call-template name="macroAdminLogin"/> + </xsl:when> + <xsl:when test="$macro='adminloginDeutsch'"> + <xsl:call-template name="macroAdminLoginDeutsch"/> + </xsl:when> + <xsl:when test="$macro='dmz'"> + <xsl:call-template name="macroDmz"/> + </xsl:when> + <xsl:otherwise> + + <xsl:variable name="macrodef" select="$node/ancestor::*[testcase-macro/@name=$macro][1]/testcase-macro[@name=$macro]"/> + + <xsl:if test="count($macrodef)=0"> + <xsl:message terminate="no"> + <xsl:text> + +------------------------------- +Syntax Error in olat-ui-map.xml +------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>Macro not defined: </xsl:text> + <xsl:value-of select="$macro"/> + <xsl:text> in scope of: element=</xsl:text> + <xsl:value-of select="name($node)"/> + <xsl:for-each select="$node/@*"> + <xsl:text> attribute: </xsl:text> + <xsl:value-of select="name()"/> + <xsl:text>=</xsl:text> + <xsl:value-of select="."/> + </xsl:for-each> + </xsl:message> + </xsl:if> + + <xsl:for-each select="$macrodef"> + <xsl:if test="count(child::*)=0"> + <xsl:text> // (!!EMPTY MACRO!!) +</xsl:text> + </xsl:if> + <xsl:for-each select="child::*"> + <xsl:choose> + <xsl:when test="name()='selenium'"> + <xsl:call-template name="macro-step-selenium"/> + </xsl:when> + <xsl:when test="name()='call-macro' and @name=$macro"> + <xsl:call-template name="resolveMacro"> + <xsl:with-param name="macro" select="@name"/> + <xsl:with-param name="node" select="$node/.."/> + </xsl:call-template> + </xsl:when> + <xsl:when test="name()='call-macro' and @name!=$macro"> + <xsl:call-template name="resolveMacro"> + <xsl:with-param name="macro" select="@name"/> + <xsl:with-param name="node" select="$node"/> + </xsl:call-template> + </xsl:when> + </xsl:choose> + </xsl:for-each> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + <xsl:text> // Step-End +</xsl:text> + + </xsl:template> + + <xsl:template name="macro-step-selenium"> + + <xsl:text> + // Step-Start: SELENIUM: </xsl:text> + + + <xsl:text>command=</xsl:text> + <xsl:value-of select="@command"/> + + <xsl:text>, target=</xsl:text> + <xsl:value-of select="@target"/> + + <xsl:text>, value=</xsl:text> + <xsl:value-of select="@value"/> + + <xsl:text> +</xsl:text> + + <xsl:choose> + <xsl:when test="@command='click'"> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="@target"/> + </xsl:call-template> + <xsl:text>"); +</xsl:text> + </xsl:when> + <xsl:when test="@command='clickAndWait'"> + <xsl:text> selenium.click("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="@target"/> + </xsl:call-template> + <xsl:text>"); + selenium.waitForPageToLoad("30000"); +</xsl:text> + </xsl:when> + <xsl:when test="@command='type'"> + <xsl:text> selenium.type("</xsl:text> + <xsl:call-template name="normalizeUiElement"> + <xsl:with-param name="uielement" select="@target"/> + </xsl:call-template> + <xsl:text>","</xsl:text> + <xsl:value-of select="@value"/> + <xsl:text>"); +</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="no"> + <xsl:text> + +---------------------------------------------------------------- +Missing API in gen_selenium-map-tests.xsl used by olatui-map.xml +---------------------------------------------------------------- + + +</xsl:text> + </xsl:message> + <xsl:message terminate="yes"> + <xsl:text>selenium command not yet defined for translation: </xsl:text> + <xsl:value-of select="@command"/> + <xsl:text> called with target=</xsl:text> + <xsl:value-of select="@target"/> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + <xsl:template name="normalizeUiElement"> + <xsl:param name="uielement"/> + <xsl:choose> + <xsl:when test="not(contains($uielement, '::'))"> + <xsl:value-of select="$uielement"/> + </xsl:when> + <xsl:when test="starts-with($uielement, 'ui=') and ends-with($uielement, ')')"> + <xsl:value-of select="$uielement"/> + </xsl:when> + <xsl:when test="not(starts-with($uielement, 'ui=')) and ends-with($uielement, ')')"> + <xsl:text>ui=</xsl:text> + <xsl:value-of select="$uielement"/> + </xsl:when> + <xsl:when test="starts-with($uielement, 'ui=') and not(ends-with($uielement, ')'))"> + <xsl:value-of select="$uielement"/> + <xsl:text>()</xsl:text> + </xsl:when> + <xsl:when test="not(starts-with($uielement, 'ui=')) and not(ends-with($uielement, ')'))"> + <xsl:text>ui=</xsl:text> + <xsl:value-of select="$uielement"/> + <xsl:text>()</xsl:text> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template name="macroAdminLogin"> + <!-- system macro --> + <xsl:choose> + <xsl:when test="$mode='slow'"> + <xsl:text> + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSeleniumAndLogin(); + assertEquals("OLAT - Home", selenium.getTitle()); +</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text> + OlatLoginHelper.olatLogin(selenium, context.getStandardAdminOlatLoginInfos()); + assertEquals("OLAT - Home", selenium.getTitle()); +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="macroAdminLoginDeutsch"> + <!-- system macro --> + <xsl:choose> + <xsl:when test="$mode='slow'"> + <xsl:text> + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + OlatLoginInfos loginInfos = context.getStandardAdminOlatLoginInfos(); + loginInfos.setLanguage("Deutsch"); + selenium = context.createSeleniumAndLogin(loginInfos); + assertEquals("OLAT - Home", selenium.getTitle()); +</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text> + OlatLoginInfos loginInfos = context.getStandardAdminOlatLoginInfos(); + loginInfos.setLanguage("Deutsch"); + OlatLoginHelper.olatLogin(selenium, loginInfos); + assertEquals("OLAT - Home", selenium.getTitle()); +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="macroDmz"> + <!-- system macro --> + <xsl:choose> + <xsl:when test="$mode='slow'"> + <xsl:text> + Context context = Context.setupContext(getFullName(), SetupType.SINGLE_VM); + selenium = context.createSelenium(); + assertEquals("OLAT - Online Learning And Training", selenium.getTitle()); +</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text> + if (selenium.isElementPresent("ui=tabs::logOut()")) { + selenium.click("ui=tabs::logOut()"); + selenium.waitForPageToLoad("30000"); + } + assertEquals("OLAT - Online Learning And Training", selenium.getTitle()); +</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/olat-ui-map-include.dtd b/src/test/profile/selenium/ui-map/resources/olat-ui-map-include.dtd new file mode 100644 index 0000000000000000000000000000000000000000..6b09e3bbcf4b9d500fbc63275f6afbc86f37dccc --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/olat-ui-map-include.dtd @@ -0,0 +1,72 @@ +<!-- + The document root. The root is a simple <ui-map> element +--> + +<!ELEMENT ui-map-include (pageset*|testcase-macro*|include*)+> + +<!ELEMENT include EMPTY> + +<!ATTLIST include + file CDATA #REQUIRED> + +<!ELEMENT pageset (pageset*|default-testcase*|testcase-macro*|xpath-ui-element*|link-ui-element*|var-link-ui-element*)*> + +<!ATTLIST pageset + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT default-testcase EMPTY> + +<!ATTLIST default-testcase + testcase CDATA #REQUIRED + final-command CDATA #REQUIRED> + +<!ELEMENT testcase-macro (call-macro*|selenium*)+> + +<!ATTLIST testcase-macro + name CDATA #REQUIRED> + +<!ELEMENT call-macro EMPTY> + +<!ATTLIST call-macro + name CDATA #REQUIRED> + +<!ELEMENT selenium EMPTY> + +<!ATTLIST selenium + command CDATA #REQUIRED + target CDATA #REQUIRED + value CDATA #IMPLIED> + +<!ELEMENT xpath-ui-element (parameter*)> + +<!ATTLIST xpath-ui-element + xpath CDATA #REQUIRED + name CDATA #REQUIRED + description CDATA #REQUIRED + testcase CDATA #IMPLIED> + +<!ELEMENT link-ui-element EMPTY> + +<!ATTLIST link-ui-element + link CDATA #REQUIRED + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT var-link-ui-element EMPTY> + +<!ATTLIST var-link-ui-element + name CDATA #REQUIRED + linkparam CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT parameter (defaultValue*)> + +<!ATTLIST parameter + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT defaultValue EMPTY> + +<!ATTLIST defaultValue + value CDATA #REQUIRED> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/olat-ui-map.dtd b/src/test/profile/selenium/ui-map/resources/olat-ui-map.dtd new file mode 100644 index 0000000000000000000000000000000000000000..56da9b0ffa53c51f608a9b1d144d7d687f68c122 --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/olat-ui-map.dtd @@ -0,0 +1,72 @@ +<!-- + The document root. The root is a simple <ui-map> element +--> + +<!ELEMENT ui-map (pageset*|testcase-macro*|include*)+> + +<!ELEMENT include EMPTY> + +<!ATTLIST include + file CDATA #REQUIRED> + +<!ELEMENT pageset (pageset*|default-testcase*|testcase-macro*|xpath-ui-element*|link-ui-element*|var-link-ui-element*)*> + +<!ATTLIST pageset + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT default-testcase EMPTY> + +<!ATTLIST default-testcase + testcase CDATA #REQUIRED + final-command CDATA #REQUIRED> + +<!ELEMENT testcase-macro (call-macro*|selenium*)+> + +<!ATTLIST testcase-macro + name CDATA #REQUIRED> + +<!ELEMENT call-macro EMPTY> + +<!ATTLIST call-macro + name CDATA #REQUIRED> + +<!ELEMENT selenium EMPTY> + +<!ATTLIST selenium + command CDATA #REQUIRED + target CDATA #REQUIRED + value CDATA #IMPLIED> + +<!ELEMENT xpath-ui-element (parameter*)> + +<!ATTLIST xpath-ui-element + xpath CDATA #REQUIRED + name CDATA #REQUIRED + description CDATA #REQUIRED + testcase CDATA #IMPLIED> + +<!ELEMENT link-ui-element EMPTY> + +<!ATTLIST link-ui-element + link CDATA #REQUIRED + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT var-link-ui-element EMPTY> + +<!ATTLIST var-link-ui-element + name CDATA #REQUIRED + linkparam CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT parameter (defaultValue*)> + +<!ATTLIST parameter + name CDATA #REQUIRED + description CDATA #REQUIRED> + +<!ELEMENT defaultValue EMPTY> + +<!ATTLIST defaultValue + value CDATA #REQUIRED> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/resolve_includes.xsl b/src/test/profile/selenium/ui-map/resources/resolve_includes.xsl new file mode 100644 index 0000000000000000000000000000000000000000..9de4bf9cd6cc49d33d5e5d3448863539a85cb266 --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/resolve_includes.xsl @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<xsl:stylesheet version="2.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:output method="xml" indent="yes" /> + + <!-- XSLT Template to copy anything, priority="-1" --> + <xsl:template match="@*|node()|text()|comment()|processing-instruction()" priority="-1"> + <xsl:call-template name="copyall"/> + </xsl:template> + + <xsl:template name="copyall"> + <xsl:copy> + <xsl:apply-templates select="@*|node()|text()|comment()|processing-instruction()"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="include"> + <xsl:apply-templates select="document(@file)/ui-map-include/child::*" /> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/resources/rollups.js b/src/test/profile/selenium/ui-map/resources/rollups.js new file mode 100644 index 0000000000000000000000000000000000000000..17f804c999642e11353d24a38fb635bd6fc1762a --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/rollups.js @@ -0,0 +1,35 @@ + +// +// ROLLUPS.JS +// ========== +// This file contains rollup definitions used in OLAT. It is attached into +// build/classes/user-extensions.js in the build.xml +// + +var myRollupManager = new RollupManager(); + +myRollupManager.addRollupRule({ + name: 'replace_click_with_clickAndWait' + , description: 'replaces commands where a click was detected with clickAndWait instead' + , alternateCommand: 'clickAndWait' + , commandMatchers: [ + { + command: 'click' + , target: 'ui=(tabs|home|groups|learningResources|course|courseEditor|group|groupManagement|qti|testEditor|userManagement)::.+\\(.*\\)' + } + ] + , expandedCommands: [] +}); + +myRollupManager.addRollupRule({ + name: 'replace_click_login_with_clickAndWait' + , description: 'replaces commands where a click was detected with clickAndWait instead' + , alternateCommand: 'clickAndWait' + , commandMatchers: [ + { + command: 'click' + , target: 'ui=dmz::login\\(.*\\)' + } + ] + , expandedCommands: [] +}); diff --git a/src/test/profile/selenium/ui-map/resources/ui-element.js b/src/test/profile/selenium/ui-map/resources/ui-element.js new file mode 100644 index 0000000000000000000000000000000000000000..cb087c8148f33ca4173be2dff2e0add4dea52fa4 --- /dev/null +++ b/src/test/profile/selenium/ui-map/resources/ui-element.js @@ -0,0 +1,1627 @@ +//****************************************************************************** +// Globals, including constants + +var UI_GLOBAL = { + UI_PREFIX: 'ui' + , XHTML_DOCTYPE: '<!DOCTYPE html PUBLIC ' + + '"-//W3C//DTD XHTML 1.0 Strict//EN" ' + + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' + , XHTML_XMLNS: 'http://www.w3.org/1999/xhtml' +}; + +//***************************************************************************** +// Exceptions + +function UIElementException(message) +{ + this.message = message; + this.name = 'UIElementException'; +} + +function UIArgumentException(message) +{ + this.message = message; + this.name = 'UIArgumentException'; +} + +function PagesetException(message) +{ + this.message = message; + this.name = 'PagesetException'; +} + +function UISpecifierException(message) +{ + this.message = message; + this.name = 'UISpecifierException'; +} + +function CommandMatcherException(message) +{ + this.message = message; + this.name = 'CommandMatcherException'; +} + +//***************************************************************************** +// UI-Element core + +/** + * The UIElement object. This has been crafted along with UIMap to make + * specifying UI elements using JSON as simple as possible. Object construction + * will fail if 1) a proper name isn't provided, 2) a faulty args argument is + * given, or 3) getLocator() returns undefined for a valid permutation of + * default argument values. See ui-doc.html for the documentation on the + * builder syntax. + * + * @param uiElementShorthand an object whose contents conform to the + * UI-Element builder syntax. + * + * @return a new UIElement object + * @throws UIElementException + */ +function UIElement(uiElementShorthand) +{ + // a shorthand object might look like: + // + // { + // name: 'topic' + // , description: 'sidebar links to topic categories' + // , args: [ + // { + // name: 'name' + // , description: 'the name of the topic' + // , defaultValues: topLevelTopics + // } + // ] + // , getLocator: function(args) { + // return this._listXPath + + // "/a[text()=" + args.name.quoteForXPath() + "]"; + // } + // , getGenericLocator: function() { + // return this._listXPath + '/a'; + // } + // // maintain testcases for getLocator() + // , testcase1: { + // // defaultValues used if args not specified + // args: { name: 'foo' } + // , xhtml: '<div id="topiclist">' + // + '<ul><li><a expected-result="1">foo</a></li></ul>' + // + '</div>' + // } + // // set a local element variable + // , _listXPath: "//div[@id='topiclist']/ul/li" + // } + // + // name cannot be null or an empty string. Enforce the same requirement for + // the description. + + /** + * Recursively returns all permutations of argument-value pairs, given + * a list of argument definitions. Each argument definition will have + * a set of default values to use in generating said pairs. If an argument + * has no default values defined, it will not be included among the + * permutations. + * + * @param args a list of UIArguments + * @param opt_inDocument (optional) + * @return a list of associative arrays containing key value pairs + */ + this.permuteArgs = function(args, opt_inDocument) { + var permutations = []; + for (var i = 0; i < args.length; ++i) { + var arg = args[i]; + var defaultValues = (arguments.length > 1) + ? arg.getDefaultValues(opt_inDocument) + : arg.getDefaultValues(); + + // skip arguments for which no default values are defined + if (defaultValues.length == 0) { + continue; + } + for (var j = 0; j < defaultValues.length; ++j) { + var value = defaultValues[j]; + var nextPermutations = this.permuteArgs(args.slice(i+1)); + if (nextPermutations.length == 0) { + var permutation = {}; + permutation[arg.name] = value + ''; // make into string + permutations.push(permutation); + } + else { + for (var k = 0; k < nextPermutations.length; ++k) { + nextPermutations[k][arg.name] = value + ''; + permutations.push(nextPermutations[k]); + } + } + } + break; + } + return permutations; + } + + + + /** + * Returns a list of all testcases for this UIElement. + */ + this.getTestcases = function() + { + return this.testcases; + } + + + + /** + * Run all unit tests, stopping at the first failure, if any. Return true + * if no failures encountered, false otherwise. See the following thread + * regarding use of getElementById() on XML documents created by parsing + * text via the DOMParser: + * + * http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/2b1b82b3c53a1282/ + */ + this.test = function() + { + var parser = new DOMParser(); + var testcases = this.getTestcases(); + testcaseLoop: for (var i = 0; i < testcases.length; ++i) { + var testcase = testcases[i]; + var xhtml = UI_GLOBAL.XHTML_DOCTYPE + '<html xmlns="' + + UI_GLOBAL.XHTML_XMLNS + '">' + testcase.xhtml + '</html>'; + var doc = parser.parseFromString(xhtml, "text/xml"); + if (doc.firstChild.nodeName == 'parsererror') { + safe_alert('Error parsing XHTML in testcase "' + testcase.name + + '" for UI element "' + this.name + '": ' + "\n" + + doc.firstChild.firstChild.nodeValue); + } + + // we're no longer using the default locators when testing, because + // args is now required + var locator = parse_locator(this.getLocator(testcase.args)); + var results; + if (locator.type == 'xpath' || (locator.type == 'implicit' && + locator.string.substring(0, 2) == '//')) { + // try using the javascript xpath engine to avoid namespace + // issues. The xpath does have to be lowercase however, it + // seems. + results = eval_xpath(locator.string, doc, + { allowNativeXpath: false, returnOnFirstMatch: true }); + } + else { + // piece the locator back together + locator = (locator.type == 'implicit') + ? locator.string + : locator.type + '=' + locator.string; + results = eval_locator(locator, doc); + } + if (results.length && results[0].hasAttribute('expected-result')) { + continue testcaseLoop; + } + + // testcase failed + if (is_IDE()) { + var msg = 'Testcase "' + testcase.name + + '" failed for UI element "' + this.name + '":'; + if (!results.length) { + msg += '\n"' + locator + '" did not match any elements!'; + } + else { + msg += '\n' + results[0] + ' was not the expected result!'; + } + safe_alert(msg); + } + return false; + } + return true; + }; + + + + /** + * Creates a set of locators using permutations of default values for + * arguments used in the locator construction. The set is returned as an + * object mapping locators to key-value arguments objects containing the + * values passed to getLocator() to create the locator. + * + * @param opt_inDocument (optional) the document object of the "current" + * page when this method is invoked. Some arguments + * may have default value lists that are calculated + * based on the contents of the page. + * + * @return a list of locator strings + * @throws UIElementException + */ + this.getDefaultLocators = function(opt_inDocument) { + var defaultLocators = {}; + if (this.args.length == 0) { + defaultLocators[this.getLocator({})] = {}; + } + else { + var permutations = this.permuteArgs(this.args, opt_inDocument); + if (permutations.length != 0) { + for (var i = 0; i < permutations.length; ++i) { + var args = permutations[i]; + var locator = this.getLocator(args); + if (!locator) { + throw new UIElementException('Error in UIElement(): ' + + 'no getLocator return value for element "' + name + + '"'); + } + defaultLocators[locator] = args; + } + } + else { + // try using no arguments. If it doesn't work, fine. + try { + var locator = this.getLocator(); + defaultLocators[locator] = {}; + } + catch (e) { + safe_log('debug', e.message); + } + } + } + return defaultLocators; + }; + + + + /** + * Validate the structure of the shorthand notation this object is being + * initialized with. Throws an exception if there's a validation error. + * + * @param uiElementShorthand + * + * @throws UIElementException + */ + this.validate = function(uiElementShorthand) + { + var msg = "UIElement validation error:\n" + print_r(uiElementShorthand); + if (!uiElementShorthand.name) { + throw new UIElementException(msg + 'no name specified!'); + } + if (!uiElementShorthand.description) { + throw new UIElementException(msg + 'no description specified!'); + } + if (!uiElementShorthand.locator + && !uiElementShorthand.getLocator + && !uiElementShorthand.xpath + && !uiElementShorthand.getXPath) { + throw new UIElementException(msg + 'no locator specified!'); + } + }; + + + + this.init = function(uiElementShorthand) + { + this.validate(uiElementShorthand); + + this.name = uiElementShorthand.name; + this.description = uiElementShorthand.description; + + // construct a new getLocator() method based on the locator property, + // or use the provided function. We're deprecating the xpath property + // and getXPath() function, but still allow for them for backwards + // compatability. + if (uiElementShorthand.locator) { + this.getLocator = function(args) { + return uiElementShorthand.locator; + }; + } + else if (uiElementShorthand.getLocator) { + this.getLocator = uiElementShorthand.getLocator; + } + else if (uiElementShorthand.xpath) { + this.getLocator = function(args) { + return uiElementShorthand.xpath; + }; + } + else { + this.getLocator = uiElementShorthand.getXPath; + } + + if (uiElementShorthand.genericLocator) { + this.getGenericLocator = function() { + return uiElementShorthand.genericLocator; + }; + } + else if (uiElementShorthand.getGenericLocator) { + this.getGenericLocator = uiElementShorthand.getGenericLocator; + } + + if (uiElementShorthand.getOffsetLocator) { + this.getOffsetLocator = uiElementShorthand.getOffsetLocator; + } + + // get the testcases and local variables + this.testcases = []; + var localVars = {}; + for (var attr in uiElementShorthand) { + if (attr.match(/^testcase/)) { + var testcase = uiElementShorthand[attr]; + if (uiElementShorthand.args && + uiElementShorthand.args.length && !testcase.args) { + safe_alert('No args defined in ' + attr + ' for UI element ' + + this.name + '! Skipping testcase.'); + continue; + } + testcase.name = attr; + this.testcases.push(testcase); + } + else if (attr.match(/^_/)) { + this[attr] = uiElementShorthand[attr]; + localVars[attr] = uiElementShorthand[attr]; + } + } + + // create the arguments + this.args = [] + this.argsOrder = []; + if (uiElementShorthand.args) { + for (var i = 0; i < uiElementShorthand.args.length; ++i) { + var arg = new UIArgument(uiElementShorthand.args[i], localVars); + this.args.push(arg); + this.argsOrder.push(arg.name); + + // if an exception is thrown when invoking getDefaultValues() + // with no parameters passed in, assume the method requires an + // inDocument parameter, and thus may only be invoked at run + // time. Mark the UI element object accordingly. + try { + arg.getDefaultValues(); + } + catch (e) { + this.isDefaultLocatorConstructionDeferred = true; + } + } + + } + + if (!this.isDefaultLocatorConstructionDeferred) { + this.defaultLocators = this.getDefaultLocators(); + } + }; + + + + this.init(uiElementShorthand); +} + +// hang this off the UIElement "namespace". This is a composite strategy. +UIElement.defaultOffsetLocatorStrategy = function(locatedElement, pageElement) { + var strategies = [ + UIElement.linkXPathOffsetLocatorStrategy + , UIElement.preferredAttributeXPathOffsetLocatorStrategy + , UIElement.simpleXPathOffsetLocatorStrategy + ]; + + for (var i = 0; i < strategies.length; ++i) { + var strategy = strategies[i]; + var offsetLocator = strategy(locatedElement, pageElement); + + if (offsetLocator) { + return offsetLocator; + } + } + + return null; +}; + +UIElement.simpleXPathOffsetLocatorStrategy = function(locatedElement, + pageElement) +{ + if (is_ancestor(locatedElement, pageElement)) { + var xpath = ""; + var recorder = Recorder.get(locatedElement.ownerDocument.defaultView); + var locatorBuilders = recorder.locatorBuilders; + var currentNode = pageElement; + + while (currentNode != null && currentNode != locatedElement) { + xpath = locatorBuilders.relativeXPathFromParent(currentNode) + + xpath; + currentNode = currentNode.parentNode; + } + + var results = eval_xpath(xpath, locatedElement.ownerDocument, + { contextNode: locatedElement }); + + if (results.length > 0 && results[0] == pageElement) { + return xpath; + } + } + + return null; +}; + +UIElement.linkXPathOffsetLocatorStrategy = function(locatedElement, pageElement) +{ + if (pageElement.nodeName == 'A' && is_ancestor(locatedElement, pageElement)) + { + var text = pageElement.textContent + .replace(/^\s+/, "") + .replace(/\s+$/, ""); + + if (text) { + var xpath = '/descendant::a[normalize-space()=' + + text.quoteForXPath() + ']'; + + var results = eval_xpath(xpath, locatedElement.ownerDocument, + { contextNode: locatedElement }); + + if (results.length > 0 && results[0] == pageElement) { + return xpath; + } + } + } + + return null; +}; + +// compare to the "xpath:attributes" locator strategy defined in the IDE source +UIElement.preferredAttributeXPathOffsetLocatorStrategy = + function(locatedElement, pageElement) +{ + // this is an ordered listing of single attributes + var preferredAttributes = [ + 'name' + , 'value' + , 'type' + , 'action' + , 'alt' + , 'title' + , 'class' + , 'src' + , 'href' + , 'onclick' + ]; + + if (is_ancestor(locatedElement, pageElement)) { + var xpathBase = '/descendant::' + pageElement.nodeName.toLowerCase(); + + for (var i = 0; i < preferredAttributes.length; ++i) { + var name = preferredAttributes[i]; + var value = pageElement.getAttribute(name); + + if (value) { + var xpath = xpathBase + '[@' + name + '=' + + value.quoteForXPath() + ']'; + + var results = eval_xpath(xpath, locatedElement.ownerDocument, + { contextNode: locatedElement }); + + if (results.length > 0 && results[0] == pageElement) { + return xpath; + } + } + } + } + + return null; +}; + + + +/** + * Constructs a UIArgument. This is mostly for checking that the values are + * valid. + * + * @param uiArgumentShorthand + * @param localVars + * + * @throws UIArgumentException + */ +function UIArgument(uiArgumentShorthand, localVars) +{ + /** + * @param uiArgumentShorthand + * + * @throws UIArgumentException + */ + this.validate = function(uiArgumentShorthand) + { + var msg = "UIArgument validation error:\n" + + print_r(uiArgumentShorthand); + + // try really hard to throw an exception! + if (!uiArgumentShorthand.name) { + throw new UIArgumentException(msg + 'no name specified!'); + } + if (!uiArgumentShorthand.description) { + throw new UIArgumentException(msg + 'no description specified!'); + } + if (!uiArgumentShorthand.defaultValues && + !uiArgumentShorthand.getDefaultValues) { + throw new UIArgumentException(msg + 'no default values specified!'); + } + }; + + + + /** + * @param uiArgumentShorthand + * @param localVars a list of local variables + */ + this.init = function(uiArgumentShorthand, localVars) + { + this.validate(uiArgumentShorthand); + + this.name = uiArgumentShorthand.name; + this.description = uiArgumentShorthand.description; + + if (uiArgumentShorthand.defaultValues) { + var defaultValues = uiArgumentShorthand.defaultValues; + this.getDefaultValues = + function() { return defaultValues; } + } + else { + this.getDefaultValues = uiArgumentShorthand.getDefaultValues; + } + + for (var name in localVars) { + this[name] = localVars[name]; + } + } + + + + this.init(uiArgumentShorthand, localVars); +} + + + +/** + * The UISpecifier constructor is overloaded. If less than three arguments are + * provided, the first argument will be considered a UI specifier string, and + * will be split out accordingly. Otherwise, the first argument will be + * considered the path. + * + * @param uiSpecifierStringOrPagesetName a UI specifier string, or the pageset + * name of the UI specifier + * @param elementName the name of the element + * @param args an object associating keys to values + * + * @return new UISpecifier object + */ +function UISpecifier(uiSpecifierStringOrPagesetName, elementName, args) +{ + /** + * Initializes this object from a UI specifier string of the form: + * + * pagesetName::elementName(arg1=value1, arg2=value2, ...) + * + * into its component parts, and returns them as an object. + * + * @return an object containing the components of the UI specifier + * @throws UISpecifierException + */ + this._initFromUISpecifierString = function(uiSpecifierString) { + var matches = /^(.*)::([^\(]+)\((.*)\)$/.exec(uiSpecifierString); + if (matches == null) { + throw new UISpecifierException('Error in ' + + 'UISpecifier._initFromUISpecifierString(): "' + + this.string + '" is not a valid UI specifier string'); + } + this.pagesetName = matches[1]; + this.elementName = matches[2]; + this.args = (matches[3]) ? parse_kwargs(matches[3]) : {}; + }; + + + + /** + * Override the toString() method to return the UI specifier string when + * evaluated in a string context. Combines the UI specifier components into + * a canonical UI specifier string and returns it. + * + * @return a UI specifier string + */ + this.toString = function() { + // empty string is acceptable for the path, but it must be defined + if (this.pagesetName == undefined) { + throw new UISpecifierException('Error in UISpecifier.toString(): "' + + this.pagesetName + '" is not a valid UI specifier pageset ' + + 'name'); + } + if (!this.elementName) { + throw new UISpecifierException('Error in UISpecifier.unparse(): "' + + this.elementName + '" is not a valid UI specifier element ' + + 'name'); + } + if (!this.args) { + throw new UISpecifierException('Error in UISpecifier.unparse(): "' + + this.args + '" are not valid UI specifier args'); + } + + uiElement = UIMap.getInstance() + .getUIElement(this.pagesetName, this.elementName); + if (uiElement != null) { + var kwargs = to_kwargs(this.args, uiElement.argsOrder); + } + else { + // probably under unit test + var kwargs = to_kwargs(this.args); + } + + return this.pagesetName + '::' + this.elementName + '(' + kwargs + ')'; + }; + + // construct the object + if (arguments.length < 2) { + this._initFromUISpecifierString(uiSpecifierStringOrPagesetName); + } + else { + this.pagesetName = uiSpecifierStringOrPagesetName; + this.elementName = elementName; + this.args = (args) ? clone(args) : {}; + } +} + + + +function Pageset(pagesetShorthand) +{ + /** + * Returns true if the page is included in this pageset, false otherwise. + * The page is specified by a document object. + * + * @param inDocument the document object representing the page + */ + this.contains = function(inDocument) + { + var urlParts = parseUri(unescape(inDocument.location.href)); + var path = urlParts.path + .replace(/^\//, "") + .replace(/\/$/, ""); + if (!this.pathRegexp.test(path)) { + return false; + } + for (var paramName in this.paramRegexps) { + var paramRegexp = this.paramRegexps[paramName]; + if (!paramRegexp.test(urlParts.queryKey[paramName])) { + return false; + } + } + if (!this.pageContent(inDocument)) { + return false; + } + + return true; + } + + + + this.getUIElements = function() + { + var uiElements = []; + for (var uiElementName in this.uiElements) { + uiElements.push(this.uiElements[uiElementName]); + } + return uiElements; + }; + + + + /** + * Returns a list of UI specifier string stubs representing all UI elements + * for this pageset. Stubs contain all required arguments, but leave + * argument values blank. Each element stub is paired with the element's + * description. + * + * @return a list of UI specifier string stubs + */ + this.getUISpecifierStringStubs = function() + { + var stubs = []; + for (var name in this.uiElements) { + var uiElement = this.uiElements[name]; + var args = {}; + for (var i = 0; i < uiElement.args.length; ++i) { + args[uiElement.args[i].name] = ''; + } + var uiSpecifier = new UISpecifier(this.name, uiElement.name, args); + stubs.push([ + UI_GLOBAL.UI_PREFIX + '=' + uiSpecifier.toString() + , uiElement.description + ]); + } + return stubs; + } + + + + /** + * Throws an exception on validation failure. + */ + this._validate = function(pagesetShorthand) + { + var msg = "Pageset validation error:\n" + + print_r(pagesetShorthand); + if (!pagesetShorthand.name) { + throw new PagesetException(msg + 'no name specified!'); + } + if (!pagesetShorthand.description) { + throw new PagesetException(msg + 'no description specified!'); + } + if (!pagesetShorthand.paths && + !pagesetShorthand.pathRegexp && + !pagesetShorthand.pageContent) { + throw new PagesetException(msg + + 'no path, pathRegexp, or pageContent specified!'); + } + }; + + + + this.init = function(pagesetShorthand) + { + this._validate(pagesetShorthand); + + this.name = pagesetShorthand.name; + this.description = pagesetShorthand.description; + + var pathPrefixRegexp = pagesetShorthand.pathPrefix + ? RegExp.escape(pagesetShorthand.pathPrefix) : ""; + var pathRegexp = '^' + pathPrefixRegexp; + + if (pagesetShorthand.paths != undefined) { + pathRegexp += '(?:'; + for (var i = 0; i < pagesetShorthand.paths.length; ++i) { + if (i > 0) { + pathRegexp += '|'; + } + pathRegexp += RegExp.escape(pagesetShorthand.paths[i]); + } + pathRegexp += ')$'; + } + else if (pagesetShorthand.pathRegexp) { + pathRegexp += '(?:' + pagesetShorthand.pathRegexp + ')$'; + } + + this.pathRegexp = new RegExp(pathRegexp); + this.paramRegexps = {}; + for (var paramName in pagesetShorthand.paramRegexps) { + this.paramRegexps[paramName] = + new RegExp(pagesetShorthand.paramRegexps[paramName]); + } + this.pageContent = pagesetShorthand.pageContent || + function() { return true; }; + this.uiElements = {}; + }; + + + + this.init(pagesetShorthand); +} + + + +/** + * Construct the UI map object, and return it. Once the object is instantiated, + * it binds to a global variable and will not leave scope. + * + * @return new UIMap object + */ +function UIMap() +{ + // the singleton pattern, split into two parts so that "new" can still + // be used, in addition to "getInstance()" + UIMap.self = this; + + // need to attach variables directly to the Editor object in order for them + // to be in scope for Editor methods + if (is_IDE()) { + Editor.uiMap = this; + Editor.UI_PREFIX = UI_GLOBAL.UI_PREFIX; + } + + this.pagesets = new Object(); + + + + /** + * pageset[pagesetName] + * regexp + * elements[elementName] + * UIElement + */ + this.addPageset = function(pagesetShorthand) + { + try { + var pageset = new Pageset(pagesetShorthand); + } + catch (e) { + safe_alert("Could not create pageset from shorthand:\n" + + print_r(pagesetShorthand) + "\n" + e.message); + return false; + } + + if (this.pagesets[pageset.name]) { + safe_alert('Could not add pageset "' + pageset.name + + '": a pageset with that name already exists!'); + return false; + } + + this.pagesets[pageset.name] = pageset; + return true; + }; + + + + /** + * @param pagesetName + * @param uiElementShorthand a representation of a UIElement object in + * shorthand JSON. + */ + this.addElement = function(pagesetName, uiElementShorthand) + { + try { + var uiElement = new UIElement(uiElementShorthand); + } + catch (e) { + safe_alert("Could not create UI element from shorthand:\n" + + print_r(uiElementShorthand) + "\n" + e.message); + return false; + } + + // run the element's unit tests only for the IDE, and only when the + // IDE is starting. Make a rough guess as to the latter condition. + if (is_IDE() && !editor.selDebugger && !uiElement.test()) { + safe_alert('Could not add UI element "' + uiElement.name + + '": failed testcases!'); + return false; + } + + try { + this.pagesets[pagesetName].uiElements[uiElement.name] = uiElement; + } + catch (e) { + safe_alert("Could not add UI element '" + uiElement.name + + "' to pageset '" + pagesetName + "':\n" + e.message); + return false; + } + + return true; + }; + + + + /** + * Returns the pageset for a given UI specifier string. + * + * @param uiSpecifierString + * @return a pageset object + */ + this.getPageset = function(uiSpecifierString) + { + try { + var uiSpecifier = new UISpecifier(uiSpecifierString); + return this.pagesets[uiSpecifier.pagesetName]; + } + catch (e) { + return null; + } + } + + + + /** + * Returns the UIElement that a UISpecifierString or pageset and element + * pair refer to. + * + * @param pagesetNameOrUISpecifierString + * @return a UIElement, or null if none is found associated with + * uiSpecifierString + */ + this.getUIElement = function(pagesetNameOrUISpecifierString, uiElementName) + { + var pagesetName = pagesetNameOrUISpecifierString; + if (arguments.length == 1) { + var uiSpecifierString = pagesetNameOrUISpecifierString; + try { + var uiSpecifier = new UISpecifier(uiSpecifierString); + pagesetName = uiSpecifier.pagesetName; + var uiElementName = uiSpecifier.elementName; + } + catch (e) { + return null; + } + } + try { + return this.pagesets[pagesetName].uiElements[uiElementName]; + } + catch (e) { + return null; + } + }; + + + + /** + * Returns a list of pagesets that "contains" the provided page, + * represented as a document object. Containership is defined by the + * Pageset object's contain() method. + * + * @param inDocument the page to get pagesets for + * @return a list of pagesets + */ + this.getPagesetsForPage = function(inDocument) + { + var pagesets = []; + for (var pagesetName in this.pagesets) { + var pageset = this.pagesets[pagesetName]; + if (pageset.contains(inDocument)) { + pagesets.push(pageset); + } + } + return pagesets; + }; + + + + /** + * Returns a list of all pagesets. + * + * @return a list of pagesets + */ + this.getPagesets = function() + { + var pagesets = []; + for (var pagesetName in this.pagesets) { + pagesets.push(this.pagesets[pagesetName]); + } + return pagesets; + }; + + + + /** + * Returns a list of elements on a page that a given UI specifier string, + * maps to. If no elements are mapped to, returns an empty list.. + * + * @param uiSpecifierString a String that specifies a UI element with + * attendant argument values + * @param inDocument the document object the specified UI element + * appears in + * @return a potentially-empty list of elements + * specified by uiSpecifierString + */ + this.getPageElements = function(uiSpecifierString, inDocument) + { + var locator = this.getLocator(uiSpecifierString); + var results = locator ? eval_locator(locator, inDocument) : []; + return results; + }; + + + + /** + * Returns the locator string that a given UI specifier string maps to, or + * null if it cannot be mapped. + * + * @param uiSpecifierString + */ + this.getLocator = function(uiSpecifierString) + { + try { + var uiSpecifier = new UISpecifier(uiSpecifierString); + } + catch (e) { + safe_alert('Could not create UISpecifier for string "' + + uiSpecifierString + '": ' + e.message); + return null; + } + + var uiElement = this.getUIElement(uiSpecifier.pagesetName, + uiSpecifier.elementName); + try { + return uiElement.getLocator(uiSpecifier.args); + } + catch (e) { + return null; + } + } + + + + /** + * Finds and returns a UI specifier string given an element and the page + * that it appears on. + * + * @param pageElement the document element to map to a UI specifier + * @param inDocument the document the element appears in + * @return a UI specifier string, or false if one cannot be + * constructed + */ + this.getUISpecifierString = function(pageElement, inDocument) + { + var is_fuzzy_match = + BrowserBot.prototype.locateElementByUIElement.is_fuzzy_match; + var pagesets = this.getPagesetsForPage(inDocument); + + for (var i = 0; i < pagesets.length; ++i) { + var pageset = pagesets[i]; + var uiElements = pageset.getUIElements(); + + for (var j = 0; j < uiElements.length; ++j) { + var uiElement = uiElements[j]; + + // first test against the generic locator, if there is one. + // This should net some performance benefit when recording on + // more complicated pages. + if (uiElement.getGenericLocator) { + var passedTest = false; + var results = + eval_locator(uiElement.getGenericLocator(), inDocument); + for (var i = 0; i < results.length; ++i) { + if (results[i] == pageElement) { + passedTest = true; + break; + } + } + if (!passedTest) { + continue; + } + } + + var defaultLocators; + if (uiElement.isDefaultLocatorConstructionDeferred) { + defaultLocators = uiElement.getDefaultLocators(inDocument); + } + else { + defaultLocators = uiElement.defaultLocators; + } + + //safe_alert(print_r(uiElement.defaultLocators)); + for (var locator in defaultLocators) { + var locatedElements = eval_locator(locator, inDocument); + if (locatedElements.length) { + var locatedElement = locatedElements[0]; + } + else { + continue; + } + + // use a heuristic to determine whether the element + // specified is the "same" as the element we're matching + if (is_fuzzy_match) { + if (is_fuzzy_match(locatedElement, pageElement)) { + return UI_GLOBAL.UI_PREFIX + '=' + + new UISpecifier(pageset.name, uiElement.name, + defaultLocators[locator]); + } + } + else { + if (locatedElement == pageElement) { + return UI_GLOBAL.UI_PREFIX + '=' + + new UISpecifier(pageset.name, uiElement.name, + defaultLocators[locator]); + } + } + + // ok, matching the element failed. See if an offset + // locator can complete the match. + if (uiElement.getOffsetLocator) { + for (var k = 0; k < locatedElements.length; ++k) { + var offsetLocator = uiElement + .getOffsetLocator(locatedElements[k], pageElement); + if (offsetLocator) { + return UI_GLOBAL.UI_PREFIX + '=' + + new UISpecifier(pageset.name, + uiElement.name, + defaultLocators[locator]) + + '->' + offsetLocator; + } + } + } + } + } + } + return false; + }; + + + + /** + * Returns a sorted list of UI specifier string stubs representing possible + * UI elements for all pagesets, paired the their descriptions. Stubs + * contain all required arguments, but leave argument values blank. + * + * @return a list of UI specifier string stubs + */ + this.getUISpecifierStringStubs = function() { + var stubs = []; + var pagesets = this.getPagesets(); + for (var i = 0; i < pagesets.length; ++i) { + stubs = stubs.concat(pagesets[i].getUISpecifierStringStubs()); + } + stubs.sort(function(a, b) { + if (a[0] < b[0]) { + return -1; + } + return a[0] == b[0] ? 0 : 1; + }); + return stubs; + } +} + +UIMap.getInstance = function() { + return (UIMap.self == null) ? new UIMap() : UIMap.self; +} + +//****************************************************************************** +// Rollups + +/** + * The Command object isn't available in the Selenium RC. We introduce an + * object with the identical constructor. In the IDE, this will be redefined, + * which is just fine. + * + * @param command + * @param target + * @param value + */ +if (typeof(Command) == 'undefined') { + function Command(command, target, value) { + this.command = command != null ? command : ''; + this.target = target != null ? target : ''; + this.value = value != null ? value : ''; + } +} + + + +/** + * A CommandMatcher object matches commands during the application of a + * RollupRule. It's specified with a shorthand format, for example: + * + * new CommandMatcher({ + * command: 'click' + * , target: 'ui=allPages::.+' + * }) + * + * which is intended to match click commands whose target is an element in the + * allPages PageSet. The matching expressions are given as regular expressions; + * in the example above, the command must be "click"; "clickAndWait" would be + * acceptable if 'click.*' were used. Here's a more complete example: + * + * new CommandMatcher({ + * command: 'type' + * , target: 'ui=loginPages::username()' + * , value: '.+_test' + * , updateArgs: function(command, args) { + * args.username = command.value; + * } + * }) + * + * Here, the command and target are fixed, but there is variability in the + * value of the command. When a command matches, the username is saved to the + * arguments object. + */ +function CommandMatcher(commandMatcherShorthand) +{ + /** + * Ensure the shorthand notation used to initialize the CommandMatcher has + * all required values. + * + * @param commandMatcherShorthand an object containing information about + * the CommandMatcher + */ + this.validate = function(commandMatcherShorthand) { + var msg = "CommandMatcher validation error:\n" + + print_r(commandMatcherShorthand); + if (!commandMatcherShorthand.command) { + throw new CommandMatcherException(msg + 'no command specified!'); + } + if (!commandMatcherShorthand.target) { + throw new CommandMatcherException(msg + 'no target specified!'); + } + if (commandMatcherShorthand.minMatches && + commandMatcherShorthand.maxMatches && + commandMatcherShorthand.minMatches > + commandMatcherShorthand.maxMatches) { + throw new CommandMatcherException(msg + 'minMatches > maxMatches!'); + } + }; + + /** + * Initialize this object. + * + * @param commandMatcherShorthand an object containing information used to + * initialize the CommandMatcher + */ + this.init = function(commandMatcherShorthand) { + this.validate(commandMatcherShorthand); + + this.command = commandMatcherShorthand.command; + this.target = commandMatcherShorthand.target; + this.value = commandMatcherShorthand.value || null; + this.minMatches = commandMatcherShorthand.minMatches || 1; + this.maxMatches = commandMatcherShorthand.maxMatches || 1; + this.updateArgs = commandMatcherShorthand.updateArgs || + function(command, args) { return args; }; + }; + + /** + * Determines whether a given command matches. Updates args by "reference" + * and returns true if it does; return false otherwise. + * + * @param command the command to attempt to match + */ + this.isMatch = function(command) { + var re = new RegExp('^' + this.command + '$'); + if (! re.test(command.command)) { + return false; + } + re = new RegExp('^' + this.target + '$'); + if (! re.test(command.target)) { + return false; + } + if (this.value != null) { + re = new RegExp('^' + this.value + '$'); + if (! re.test(command.value)) { + return false; + } + } + + // okay, the command matches + return true; + }; + + // initialization + this.init(commandMatcherShorthand); +} + + + +function RollupRuleException(message) +{ + this.message = message; + this.name = 'RollupRuleException'; +} + +function RollupRule(rollupRuleShorthand) +{ + /** + * Ensure the shorthand notation used to initialize the RollupRule has all + * required values. + * + * @param rollupRuleShorthand an object containing information about the + * RollupRule + */ + this.validate = function(rollupRuleShorthand) { + var msg = "RollupRule validation error:\n" + + print_r(rollupRuleShorthand); + if (!rollupRuleShorthand.name) { + throw new RollupRuleException(msg + 'no name specified!'); + } + if (!rollupRuleShorthand.description) { + throw new RollupRuleException(msg + 'no description specified!'); + } + // rollupRuleShorthand.args is optional + if (!rollupRuleShorthand.commandMatchers && + !rollupRuleShorthand.getRollup) { + throw new RollupRuleException(msg + + 'no command matchers specified!'); + } + if (!rollupRuleShorthand.expandedCommands && + !rollupRuleShorthand.getExpandedCommands) { + throw new RollupRuleException(msg + + 'no expanded commands specified!'); + } + + return true; + }; + + /** + * Initialize this object. + * + * @param rollupRuleShorthand an object containing information used to + * initialize the RollupRule + */ + this.init = function(rollupRuleShorthand) { + this.validate(rollupRuleShorthand); + + this.name = rollupRuleShorthand.name; + this.description = rollupRuleShorthand.description; + this.pre = rollupRuleShorthand.pre || ''; + this.post = rollupRuleShorthand.post || ''; + this.alternateCommand = rollupRuleShorthand.alternateCommand; + this.args = rollupRuleShorthand.args || []; + + if (rollupRuleShorthand.commandMatchers) { + // construct the rule from the list of CommandMatchers + this.commandMatchers = []; + var matchers = rollupRuleShorthand.commandMatchers; + for (var i = 0; i < matchers.length; ++i) { + if (matchers[i].updateArgs && this.args.length == 0) { + // enforce metadata for arguments + var msg = "RollupRule validation error:\n" + + print_r(rollupRuleShorthand) + + 'no argument metadata provided!'; + throw new RollupRuleException(msg); + } + this.commandMatchers.push(new CommandMatcher(matchers[i])); + } + + // returns false if the rollup doesn't match, or a rollup command + // if it does. If returned, the command contains the + // replacementIndexes property, which indicates which commands it + // substitutes for. + this.getRollup = function(commands) { + // this is a greedy matching algorithm + var replacementIndexes = []; + var commandMatcherQueue = this.commandMatchers; + var matchCount = 0; + var args = {}; + for (var i = 0, j = 0; i < commandMatcherQueue.length;) { + var matcher = commandMatcherQueue[i]; + if (j >= commands.length) { + // we've run out of commands! If the remaining matchers + // do not have minMatches requirements, this is a + // match. Otherwise, it's not. + if (matcher.minMatches > 0) { + return false; + } + ++i; + matchCount = 0; // unnecessary, but let's be consistent + } + else { + if (matcher.isMatch(commands[j])) { + ++matchCount; + if (matchCount == matcher.maxMatches) { + // exhausted this matcher's matches ... move on + // to next matcher + ++i; + matchCount = 0; + } + args = matcher.updateArgs(commands[j], args); + replacementIndexes.push(j); + ++j; // move on to next command + } + else { + //alert(matchCount + ', ' + matcher.minMatches); + if (matchCount < matcher.minMatches) { + return false; + } + // didn't match this time, but we've satisfied the + // requirements already ... move on to next matcher + ++i; + matchCount = 0; + // still gonna look at same command + } + } + } + + var rollup; + if (this.alternateCommand) { + rollup = new Command(this.alternateCommand, + commands[0].target, commands[0].value); + } + else { + rollup = new Command('rollup', this.name); + rollup.value = to_kwargs(args); + } + rollup.replacementIndexes = replacementIndexes; + return rollup; + }; + } + else { + this.getRollup = function(commands) { + var result = rollupRuleShorthand.getRollup(commands); + if (result) { + var rollup = new Command( + result.command + , result.target + , result.value + ); + rollup.replacementIndexes = result.replacementIndexes; + return rollup; + } + return false; + }; + } + + this.getExpandedCommands = function(kwargs) { + var commands = []; + var expandedCommands = (rollupRuleShorthand.expandedCommands + ? rollupRuleShorthand.expandedCommands + : rollupRuleShorthand.getExpandedCommands( + parse_kwargs(kwargs))); + for (var i = 0; i < expandedCommands.length; ++i) { + var command = expandedCommands[i]; + commands.push(new Command( + command.command + , command.target + , command.value + )); + } + return commands; + }; + }; + + this.init(rollupRuleShorthand); +} + + + +/** + * + */ +function RollupManager() +{ + // singleton pattern + RollupManager.self = this; + + this.init = function() + { + this.rollupRules = {}; + if (is_IDE()) { + Editor.rollupManager = this; + } + }; + + /** + * Adds a new RollupRule to the repository. Returns true on success, or + * false if the rule couldn't be added. + * + * @param rollupRuleShorthand shorthand JSON specification of the new + * RollupRule, possibly including CommandMatcher + * shorthand too. + * @return true if the rule was added successfully, + * false otherwise. + */ + this.addRollupRule = function(rollupRuleShorthand) + { + try { + var rule = new RollupRule(rollupRuleShorthand); + this.rollupRules[rule.name] = rule; + } + catch(e) { + smart_alert("Could not create RollupRule from shorthand:\n\n" + + e.message); + return false; + } + return true; + }; + + /** + * Returns a RollupRule by name. + * + * @param rollupName the name of the rule to fetch + * @return the RollupRule, or null if it isn't found. + */ + this.getRollupRule = function(rollupName) + { + return (this.rollupRules[rollupName] || null); + }; + + /** + * Returns a list of name-description pairs for use in populating the + * auto-populated target dropdown in the IDE. Rules that have an alternate + * command defined are not included in the list, as they are not bona-fide + * rollups. + * + * @return a list of name-description pairs + */ + this.getRollupRulesForDropdown = function() + { + var targets = []; + var names = keys(this.rollupRules).sort(); + for (var i = 0; i < names.length; ++i) { + var name = names[i]; + if (this.rollupRules[name].alternateCommand) { + continue; + } + targets.push([ name, this.rollupRules[name].description ]); + } + return targets; + }; + + /** + * Applies all rules to the current editor commands, asking the user in + * each case if it's okay to perform the replacement. The rules are applied + * repeatedly until there are no more matches. The algorithm should + * remember when the user has declined a replacement, and not ask to do it + * again. + * + * @return the list of commands with rollup replacements performed + */ + this.applyRollupRules = function() + { + var commands = editor.getTestCase().commands; + var blacklistedRollups = {}; + + // so long as rollups were performed, we need to keep iterating through + // the commands starting at the beginning, because further rollups may + // potentially be applied on the newly created ones. + while (true) { + var performedRollup = false; + for (var i = 0; i < commands.length; ++i) { + // iterate through commands + for (var rollupName in this.rollupRules) { + var rule = this.rollupRules[rollupName]; + var rollup = rule.getRollup(commands.slice(i)); + if (rollup) { + // since we passed in a sliced version of the commands + // array to the getRollup() method, we need to re-add + // the offset to the replacementIndexes + var k = 0; + for (; k < rollup.replacementIndexes.length; ++k) { + rollup.replacementIndexes[k] += i; + } + + // build the confirmation message + var msg = "Perform the following command rollup?\n\n"; + for (k = 0; k < rollup.replacementIndexes.length; ++k) { + var replacementIndex = rollup.replacementIndexes[k]; + var command = commands[replacementIndex]; + msg += '[' + replacementIndex + ']: '; + msg += command + "\n"; + } + msg += "\n"; + msg += rollup; + + // check against blacklisted rollups + if (blacklistedRollups[msg]) { + continue; + } + + // highlight the potentially replaced rows + for (k = 0; k < commands.length; ++k) { + var command = commands[k]; + command.result = ''; + if (rollup.replacementIndexes.indexOf(k) != -1) { + command.selectedForReplacement = true; + } + editor.view.rowUpdated(replacementIndex); + } + + // get confirmation from user + if (confirm(msg)) { + // perform rollup + var deleteRanges = []; + var replacementIndexes = rollup.replacementIndexes; + for (k = 0; k < replacementIndexes.length; ++k) { + // this is expected to be list of ranges. A + // range has a start, and a list of commands. + // The deletion only checks the length of the + // command list. + deleteRanges.push({ + start: replacementIndexes[k] + , commands: [ 1 ] + }); + } + editor.view.executeAction(new TreeView + .DeleteCommandAction(editor.view,deleteRanges)); + editor.view.insertAt(i, rollup); + + performedRollup = true; + } + else { + // cleverly remember not to try this rollup again + blacklistedRollups[msg] = true; + } + + // unhighlight + for (k = 0; k < commands.length; ++k) { + commands[k].selectedForReplacement = false; + editor.view.rowUpdated(k); + } + } + } + } + if (!performedRollup) { + break; + } + } + return commands; + }; + + this.init(); +} + +RollupManager.getInstance = function() { + return (RollupManager.self == null) + ? new RollupManager() + : RollupManager.self; +} + diff --git a/src/test/profile/selenium/ui-map/rightsManagement-pageset.xml b/src/test/profile/selenium/ui-map/rightsManagement-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2dfaf6c7e26127e7707c47dfbe2640ed6c35b1e --- /dev/null +++ b/src/test/profile/selenium/ui-map/rightsManagement-pageset.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="rightsManagement" description="the rights management of a course"> + <xpath-ui-element name="AllRightGroups" xpath="//a[contains(text(),'All right groups')]" description="shows all right groups"/> + + <xpath-ui-element name="createRightsGroup" xpath="//div[@class='b_toolbox']//li//a[contains(.//span/text(),'New right group')]" description="left navigation link 'New right group'"/> + <pageset name="rightGroups" description="tab 'All Right Groups'"> + <xpath-ui-element name="close" xpath="//div[@class='b_toolbox'][descendant::text()='Rights management']//a[descendant::text()='Close']" description="Close Rights Management"/> + <xpath-ui-element name="openRightGroup" xpath="//td[1]/a[2]" description="opens first Right group"/> + <pageset name="rightGroup" description="Right Group"> + <link-ui-element name="calendar" link="Calendar" description="opens Calendar"/> + <xpath-ui-element name="course" xpath="//div[@id='b_col1']//div[@class='b_tree']//li//a[text()='Course']" description="closes calendar View"/> + <xpath-ui-element name="startCourse" xpath="//div[contains(@class,'b_table_wrapper')]//form//td[text()='" + courseName + "']/..//a[text()='Start']" description="opens Course"> + <parameter name="courseName" description="The name of the course" /> + </xpath-ui-element> + </pageset> + </pageset> + + <pageset name="members" description="tab 'Members'"> + <xpath-ui-element name="addUser" xpath="//div[1]/div/span[2]/a/span" description="button 'Add user(s)'"/> + <xpath-ui-element name="selectUser" xpath="document.forms[3].elements[0]" description="checkbox next to the member when adding a user"/> + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/systemAdministration-pageset.xml b/src/test/profile/selenium/ui-map/systemAdministration-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..50fd8c25f0b9c9754fe67a358efa9c2cf220521c --- /dev/null +++ b/src/test/profile/selenium/ui-map/systemAdministration-pageset.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> +<pageset name="systemInformation" description="the system information tab set"> + <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[text()='infomsg']" name="infoMsgTab" + description="the info message tab" /> + <xpath-ui-element xpath="//a[@class='b_button' and contains(./span/text(), 'Edit message')]" name="infoMsgEditButton" + description="the info message edit button" /> + <!-- <xpath-ui-element xpath="//form[@name='infoMsgForm']//textarea[@name='infomsg']" name="infoMsgTextarea" + description="the info message text area" /> unused --> + <xpath-ui-element xpath="//form[@name='infoMsgForm']//input[@value='Save']" name="info msg save button" + description="save the info message" /> +</pageset> +</ui-map-include> + + + + + diff --git a/src/test/profile/selenium/ui-map/tabs-pageset.xml b/src/test/profile/selenium/ui-map/tabs-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..9557ea205f84379bb5c69cf9a7490f66b4103f44 --- /dev/null +++ b/src/test/profile/selenium/ui-map/tabs-pageset.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="tabs" description="The main OLAT tabs"> + <default-testcase testcase="login" final-command="clickAndWait"/> + <testcase-macro name="lx"> + <call-macro name="login"/> + </testcase-macro> + + <xpath-ui-element name="home" xpath="//a[span/text()='Home']" description="main tab 'Home'" testcase="lx/tabs::home"/> + <xpath-ui-element name="groups" xpath="//a[span/text()='Groups']" description="main tab 'Groups'"/> + <xpath-ui-element name="learningResources" xpath="//a[span/text()='Learning resources']" description="main tab 'Learning resources'"/> + <xpath-ui-element name="groupAdministration" xpath="//a[span/text()='Group administration']" description="main tab 'Group administration'"/> + <xpath-ui-element name="userManagement" xpath="//a[span/text()='User management']" description="main tab 'User management'"/> + <xpath-ui-element name="administration" xpath="//a[span/text()='Administration']" description="main tab 'Administration'"/> + <xpath-ui-element name="closeCourse" xpath="//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfCourse+"']" description="Close an open course" testcase=""> + <parameter name="nameOfCourse" description="the name of the course"> + <defaultValue value="Demo Course"/> + <defaultValue value="Demo course wiki"/> + <defaultValue value="test"/><!-- closes a group named "test" --> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="selectCourse" xpath="//a[descendant::span[@title='"+nameOfCourse+"']]" description="select course tab"> + <parameter name="nameOfCourse" description="the name of the course"/> + </xpath-ui-element> + <xpath-ui-element name="closeAnyCourse" xpath="//a[contains(@class, 'b_nav_tab_close')]" description="close any course, hopefully it is ony one open"></xpath-ui-element> + <xpath-ui-element name="closeGroup" xpath="//li[contains(@class, 'b_resource_BusinessGroup')]//a[contains(@class, 'b_nav_tab_close') and ../..//@title='"+nameOfGroup+"']" description="Close a group" testcase=""> + <parameter name="nameOfGroup" description="the name of the group"> + <defaultValue value="test"/> <!-- closes a group named "test" --> + </parameter> + </xpath-ui-element> + <xpath-ui-element name="closeNavTab" xpath="//a[contains(@class, 'b_nav_tab_close')]" description="Close a navigation tab" testcase=""/> + + <xpath-ui-element name="logOut" xpath="//a[@id='b_logout']" description="The logout link"/> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/testEditor-pageset.xml b/src/test/profile/selenium/ui-map/testEditor-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..f2c92c0ab794d25469e8e52018ffbe22712ba9e9 --- /dev/null +++ b/src/test/profile/selenium/ui-map/testEditor-pageset.xml @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="testEditor" description="A test opened in the editor"> + <pageset name="menu" description="the left hand menu"> + <var-link-ui-element name="link" linkparam="link" description="a node in the test editor"/> + </pageset> + <pageset name="content" description="the (center) content area"> + <pageset name="test" description="tab test (top node)"> + <!-- <xpath-ui-element name="title" xpath="//form[@name='assessform']//input[@name='title']" description="The title input field"/> + <xpath-ui-element name="description" xpath="//form[@name='assessform']//textarea[@name='objectives']" description="The Description input field"/> + <xpath-ui-element name="timeLimitYes" xpath="//form[@name='assessform']//input[@name='duration' and @value='Yes']" description="Radio Button (Yes) time limit"/> + <xpath-ui-element name="timeLimitNo" xpath="//form[@name='assessform']//input[@name='duration' and @value='No']" description="Radio Button (No) time limit"/> + <xpath-ui-element name="timeLimitMin" xpath="//form[@name='assessform']//input[@name='duration_min']" description="Field time limit minutes"/> + <xpath-ui-element name="timeLimitSec" xpath="//form[@name='assessform']//input[@name='duration_sec']" description="Field time limit seconds"/> + <xpath-ui-element name="setFeedbackYes" xpath="//form[@name='assessform']//input[@name='inheritswitch' and @value='Yes']" description="Radio Button set feedback/solution for entire text to Yes"/> + <xpath-ui-element name="setFeedbackNo" xpath="//form[@name='assessform']//input[@name='inheritswitch' and @value='No']" description="Radio Button set feedback/solution for entire text to No"/> asa unused --> + <xpath-ui-element name="necessaryPassingScore" xpath="//form[@name='assessform']//input[@name='cutvalue']" description="Field necessary passing score"/> + <xpath-ui-element name="save" xpath="//form[@name='assessform']//input[@value='Save']" description="The Save button"/> + </pageset> + <pageset name="section" description="tab section (section node)"> + <xpath-ui-element name="title" xpath="//form[@id='ofo_tab_section']//input[@name='title']" description="The title input field"/> + <!-- <xpath-ui-element name="description" xpath="//form[@id='ofo_tab_section']//textarea[@name='objectives']" description="The Description input field"/> + <xpath-ui-element name="timeLimitSectionYes" xpath="//form[@id='ofo_tab_section']//input[@name='duration' and @value='Yes']" description="Radio Button (Yes) time limit for entire section"/> + <xpath-ui-element name="timeLimitSectionNo" xpath="//form[@id='ofo_tab_section']//input[@name='duration' and @value='No']" description="Radio Button (No) time limit for entire section"/> + <xpath-ui-element name="timeLimitMin" xpath="//form[@id='ofo_tab_section']//input[@name='duration_min']" description="Field time limit minutes"/> + <xpath-ui-element name="timeLimitSec" xpath="//form[@id='ofo_tab_section']//input[@name='duration_sec']" description="Field time limit seconds"/> + <xpath-ui-element name="nrOfQuestions" xpath="//select[@name='selection_number']" description="Drop down number of questions in this section"/> asa unused --> + <xpath-ui-element name="orderOfQuestions" xpath="//select[@name='order_type']" description="Drop down order of questions"/> + <xpath-ui-element name="save" xpath="//form[@id='ofo_tab_section']//input[@value='Save']" description="The Save button"/> + </pageset> + <pageset name="metadata" description="tab metadata on question level"> + <!-- <xpath-ui-element name="tabMetadata" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Meta data']" description="Tab Meta data"/> + <xpath-ui-element name="title" xpath="//form[@name='itemMetaDataForm']//input[@name='title']" description="The title input field"/> + <xpath-ui-element name="description" xpath="//form[@name='itemMetaDataForm']//textarea[@name='descr']" description="The Description input field"/> asa unused --> + <xpath-ui-element name="mcType" xpath="//div[@class='b_form_element' and .//text()='Multiple choice']" description="the question type"/> + <xpath-ui-element name="scType" xpath="//div[@class='b_form_element' and .//text()='Single choice']" description="the question type"/> + <xpath-ui-element name="gapType" xpath="//div[@class='b_form_element' and .//text()='Gap text']" description="the question type"/> + <xpath-ui-element name="kprimType" xpath="//div[@class='b_form_element' and .//text()='Kprim']" description="the question type"/> + <xpath-ui-element name="essayType" xpath="//div[@class='b_form_element' and .//text()='Text']" description="the question type"/> + <!-- <xpath-ui-element name="alignment" xpath="//form[@name='itemMetaDataForm']//select[@name='layout']" description="The alignment of answers drop-down"/> + <xpath-ui-element name="limitAttemptsYes" xpath="//form[@name='itemMetaDataForm']//input[@name='limittries' and @value='y']" description="Limit number of attempts: Yes"/> + <xpath-ui-element name="limitAttemptsNo" xpath="//form[@name='itemMetaDataForm']//input[@name='limittries' and @value='n']" description="Limit number of attempts: No"/> + <xpath-ui-element name="nrOfAttempts" xpath="//form[@name='itemMetaDataForm']//input[@name='tries']" description="Field number of attempts"/> + <xpath-ui-element name="timeLimitYes" xpath="//form[@name='itemMetaDataForm']//input[@name='limittime' and @value='y']" description="Radio Button (Yes) time limit"/> + <xpath-ui-element name="timeLimitNo" xpath="//form[@name='itemMetaDataForm']//input[@name='limittime' and @value='n']" description="Radio Button (No) time limit"/> + <xpath-ui-element name="timeLimitMin" xpath="//form[@name='itemMetaDataForm']//input[@name='timemin']" description="Field time limit minutes"/> + <xpath-ui-element name="timeLimitSec" xpath="//form[@name='itemMetaDataForm']//input[@name='timesek']" description="Field time limit seconds"/> + <xpath-ui-element name="randomOrderAnswersYes" xpath="//form[@name='itemMetaDataForm']//input[@name='shuffle' and @value='y']" description="Radio Button (Yes) random order of answers"/> + <xpath-ui-element name="randomOrderAnswersNo" xpath="//form[@name='itemMetaDataForm']//input[@name='shuffle' and @value='n']" description="Radio Button (No) random order of answers"/> + <xpath-ui-element name="showHintsYes" xpath="//form[@name='itemMetaDataForm']//input[@name='showSolutionHints' and @value='y']" description="Radio Button (Yes) show hints"/> + <xpath-ui-element name="showHintsNo" xpath="//form[@name='itemMetaDataForm']//input[@name='showSolutionHints' and @value='n']" description="Radio Button (No) show hints"/> + <xpath-ui-element name="hints" xpath="//form[@name='itemMetaDataForm']//textarea[@name='solutionHints']" description="Field hints"/> + <xpath-ui-element name="showSolutionYes" xpath="//form[@name='itemMetaDataForm']//input[@name='showCorrectSolution' and @value='y']" description="Radio Button (Yes) show correct solution"/> + <xpath-ui-element name="showSolutionNo" xpath="//form[@name='itemMetaDataForm']//input[@name='showCorrectSolution' and @value='n']" description="Radio Button (No) show correct solution"/> + <xpath-ui-element name="correctSolution" xpath="//form[@name='itemMetaDataForm']//textarea[@name='correctSolution']" description="Field correct solution"/> + <xpath-ui-element name="save" xpath="//form[@name='itemMetaDataForm']//input[@value='Save']" description="The Save button"/> asa unused --> + </pageset> + <pageset name="questionAnswers" description="tab question/answers on question level"> + <xpath-ui-element name="tabQuestionAnswers" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Question/answers']" description="Tab Question/Answers"/> + <xpath-ui-element name="editQuestion" xpath="//fieldset[./legend/text()='Question']//a[@title='Edit this question ']" description="edit a question"/> + + <pageset name="editMaterial" description="question or answer editor"> + <!-- <xpath-ui-element name="moveUp" xpath="//fieldset[./legend/text()='Edit material ']//a[@title='Move element upwards']" description="move question upwards"/> asa unused --> + <!-- <xpath-ui-element name="moveDown" xpath="//fieldset[./legend/text()='Edit material ']//a[@title='Move element downwards']" description="move question downwards"/> asa unused --> + </pageset> + <!-- <xpath-ui-element name="moveAnswerUp" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[1]/a[@title='Move element upwards']" description="Move an answer up"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="moveAnswerDown" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[1]/a[@title='Move element downwards']" description="Move an answer down"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="moveAnswerUpMc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "+1]/td[1]/a[@title='Move element upwards']" description="Move a mc answer up"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="moveAnswerDownMc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[1]/a[@title='Move element downwards']" description="Move a mc answer down"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> asa unused --> + <xpath-ui-element name="setCorrectSc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[3]/input" description="Set a particular sc answer as correct"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="setCorrectKprim" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[3]/input" description="Set a particular kprim answer as correct"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="setIncorrectKprim" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[4]/input" description="Set a particular kprim answer as incorrect"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="setCorrectMc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "+1]/td[3]/input" description="Set a particular mc answer as correct"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="editAnswerMc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "+1]//a[@title='Edit this answering material ']" description="Edit a mc answer"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="editAnswerKprim" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td[5]/a[@title='Edit this answering material ']" description="Edit a kprim answer"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="editAnswerRest" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]//a[@title='Edit this answering material ']" description="Edit an answer"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <!-- <xpath-ui-element name="deleteAnswerMc" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "+1]/td/a[@title='Delete']" description="Delete an answer"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> + <xpath-ui-element name="deleteAnswerRest" xpath="//fieldset[./legend/text()='Answers']//table//tbody/tr[" + indexOfAnswer + "]/td/a[@title='Delete this text']" description="Delete an answer"> + <parameter name="indexOfAnswer" description="the index of the answer, starting with 1"/> + </xpath-ui-element> asa unused --> + <xpath-ui-element name="addNewAnswer" xpath="//fieldset[./legend/text()='Answers']//form//a[./span/text()='Add new answer ']" description="add new answer button"/> + <xpath-ui-element name="addNewTextFragment" xpath="//form[@id='ofo_tab_fibitem']//a[./span/text()='Add new text fragment ']" description="add new text fragment button"/> + <xpath-ui-element name="addNewBlank" xpath="//form[@id='ofo_tab_fibitem']//a[./span/text()='Add new blank']" description="add new blank button"/> + <xpath-ui-element name="blankField" xpath="//fieldset[./legend/text()='Answers']//table[1]//tbody/tr[" + indexOfElement + "]/td/input[contains(@name, 'content_')]" description="type in the blank field"> + <parameter name="indexOfElement" description="the index of the answer, starting with 1, count from the top, including text"/> + </xpath-ui-element> + <!-- <xpath-ui-element name="methodOfAssessment" xpath="//select[@name='valuation_method']" description="dropdown method of assessment (multiple choice, gap text)"/> + <xpath-ui-element name="score" xpath="//fieldset[./legend/text()='Answers']//form//input[@name='single_score']" description="Field score (Score all correct answers in case of FIB and MC item)"/> + <xpath-ui-element name="minimumScore" xpath="//fieldset[./legend/text()='Answers']//form//input[@name='min_value']" description="Field minimum score"/> + <xpath-ui-element name="maximumScore" xpath="//fieldset[./legend/text()='Answers']//form//input[@name='max_value']" description="Field maximum score)"/> + <xpath-ui-element name="numberOfCharacters" xpath="//fieldset[./legend/text()='Answers']//table[1]//tbody/tr[" + indexOfElement + "]/td/input[contains(@name, 'size_')]" description="field number of characters"> + <parameter name="indexOfElement" description="index of field (row)"/> + </xpath-ui-element> + <xpath-ui-element name="lengthOfGap" xpath="//fieldset[./legend/text()='Answers']//table[1]//tbody/tr[" + indexOfElement + "]/td/input[contains(@name, 'maxl_')]" description="field length of gap"> + <parameter name="indexOfElement" description="index of field (row)"/> + </xpath-ui-element> asa unused --> + <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='Answers']//form//input[@value='Save']" description="save button"/> + <xpath-ui-element name="capitalization" xpath="//fieldset[./legend/text()='Answers']//table[1]//tbody/tr[" + indexOfElement + "]/td/input[contains(@name, 'case_') and @value='Yes']" description="check box capitalization (Yes)"> + <parameter name="indexOfElement" description="the index of the checkbox"/> + </xpath-ui-element> + + <xpath-ui-element name="essayLettersPerLine" xpath="//input[@name='columns_q']" description="essay answer size: letters per line"/> + <xpath-ui-element name="essayNumberOfLines" xpath="//input[@name='rows_q']" description="essay answer size: number of lines"/> + </pageset> + <pageset name="feedback" description="tab feedback on question level"> + <!-- <xpath-ui-element name="tabFeedback" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Feedback']" description="tab feedback"/> + <xpath-ui-element name="showFeedbackYes" xpath="//form[@id='ofo_tab_feedback']//input[@name='feedbackswitch' and @value='Yes']" description="Radio Button (Yes) show feedback"/> + <xpath-ui-element name="showFeedbackNo" xpath="//form[@id='ofo_tab_feedback']//input[@name='feedbackswitch' and @value='No']" description="Radio Button (No) show feedback"/> + <xpath-ui-element name="feedbackAllCorrectAnswers" xpath="//form[@id='ofo_tab_feedback']//textarea[@name='feedback_mastery']" description="Field feedback for all correct answers"/> + <xpath-ui-element name="feedbackWrongAnswer" xpath="//form[@id='ofo_tab_feedback']//textarea[@name='feedback_fail']" description="Field feedback for wrong answer"/> asa unused --> + + <!--be aware that following link is dependent on name of answer --> + <!-- <xpath-ui-element name="feedbackForSpecifiedAnswer" xpath="//form[@id='ofo_tab_feedback']//textarea[@name='feedback_q0']" description="Field feedback for answer specified before"/> + <xpath-ui-element name="saveChanges" xpath="//fieldset[./legend/text()='Feedback']//form//input[@value='Save changes']" description="save changes button"/> asa unused --> + </pageset> + <pageset name="questionPreview" description="tab question preview on question level"> + <!-- <xpath-ui-element name="tabQuestionPreview" xpath="//div[@class='b_tabbedpane_tabs']//a[.//text()='Question preview']" description="tab question preview"/> asa unused --> + </pageset> + </pageset> + <pageset name="toolbox" description="the toolbox area to the right"> + <pageset name="editorTools" description="the editor tools toolbox"> + <!-- <xpath-ui-element name="testPreview" xpath="//div[@class='b_toolbox'][descendant::text()='Editor tools']//a[descendant::text()='Preview']" description="the Preview link in the Editor tools toolbox"/> asa unused --> + <xpath-ui-element name="closeEditor" xpath="//div[@class='b_toolbox'][descendant::text()='Editor tools']//a[contains(descendant::text(), 'Close/save')]" description="the Close/save link in the Editor tools toolbox"/> + </pageset> + <pageset name="add" description="the add toolbox"> + <xpath-ui-element name="addSection" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Section']" description="The Section link in the add toolbox"/> + <xpath-ui-element name="addSingleChoice" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Single choice']" description="The Single choice link in the add toolbox"/> + <xpath-ui-element name="addMultipleChoice" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Multiple choice']" description="The Multiple choice link in the add toolbox"/> + <xpath-ui-element name="addKprim" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Kprim']" description="The Kprim link in the add toolbox"/> + <xpath-ui-element name="addGapText" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Gap text']" description="The Gap text link in the add toolbox"/> + <xpath-ui-element name="addText" xpath="//div[@class='b_toolbox'][descendant::text()='Add']//a[descendant::text()='Text']" description="The text link in the add toolbox"/> + <xpath-ui-element name="insertAsRootsFirstChild" xpath="//div[@class='b_selectiontree_content']//input[@class='b_radio']" description="Choose first child of root"/> + <xpath-ui-element name="save" xpath="//div[@class='b_selectiontree']//button[.//text()='Save']" description="The save button of inserting test elements"/> + </pageset> + <pageset name="Change" description="the Change toolbox"> + <xpath-ui-element name="changeDelete" xpath="//div[@class='b_toolbox'][descendant::text()='Change']//a[contains(descendant::text(), 'Delete')]" description="the Delete link in the Change toolbox"/> + <!-- <xpath-ui-element name="changeMove" xpath="//div[@class='b_toolbox'][descendant::text()='Change']//a[contains(descendant::text(), 'Move')]" description="the Delete link in the Change toolbox"/> asa unused --> + <xpath-ui-element name="changeCopy" xpath="//div[@class='b_toolbox'][descendant::text()='Change']//a[contains(descendant::text(), 'Copy')]" description="the Delete link in the Change toolbox"/> + </pageset> + </pageset> + <pageset name="dialog" description="all dialogs in the test editor"> + <xpath-ui-element xpath="//div[contains(.//text(), 'Close/save editor')]/..//a[.//text()='Save']" name="clickSave" description="save button when closing the testeditor"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Close/save editor')]/..//a[.//text()='Discard']" name="clickDiscard" description="Discard button when closing the testeditor"></xpath-ui-element> + <xpath-ui-element xpath="//div[contains(.//text(), 'Close/save editor')]/..//a[.//text()='Cancel']" name="clickCancel" description="Cancel button when closing the testeditor"></xpath-ui-element> asa unused --> + <xpath-ui-element xpath="//div[contains(@class, 'x-window-dlg')]//button[text()='OK']" name="clickOk" description="Ok button after error deleting item"></xpath-ui-element> + <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/..//a[.//text()='Yes']" name="clickYes" description="confirm yes of dialog when deleting item"></xpath-ui-element> + <!-- <xpath-ui-element xpath="//div[contains(.//text(), 'Do you really want to delete')]/..//a[.//text()='No']" name="clickNo" description="confirm no of dialog when deleting item"></xpath-ui-element> asa unused --> + + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file diff --git a/src/test/profile/selenium/ui-map/userAdministration-pageset.xml b/src/test/profile/selenium/ui-map/userAdministration-pageset.xml new file mode 100644 index 0000000000000000000000000000000000000000..d6539779860a21cdc99bd5246f6e885c0cd68f46 --- /dev/null +++ b/src/test/profile/selenium/ui-map/userAdministration-pageset.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE ui-map-include PUBLIC "olat/ui-map-include" "resources/olat-ui-map-include.dtd"> + +<ui-map-include> + <pageset name="userManagement" description="user management open"> + <pageset name="menu" description="menu on the left hand side"> + <xpath-ui-element name="userManagement" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='User management']" description="user management link in the menu"/> + <xpath-ui-element name="userSearch" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='User search']" description="user search link in the menu"/> + <xpath-ui-element name="createUser" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Create user']" description="create user link in the menu"/> + <xpath-ui-element name="importUsers" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Import users']" description="import users link in the menu"/> + <xpath-ui-element name="deleteUser" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Delete user']" description="delete user link in the menu"/> + <xpath-ui-element name="deleteUserImmediately" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Delete user immediately']" description="delete user immediately link in the menu"/> + <xpath-ui-element name="usersReplayURL" xpath="//div[@class='b_tree']//a[descendant-or-self::text()='Users ReplayURL and AJAX ']" description="users replay URL in menu"></xpath-ui-element> + </pageset> + <pageset name="content" description="content of user management"> + <pageset name="userSearch" description="user search form"> + <testcase-macro name="go"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="tabs::userManagement"/> + </testcase-macro> + <default-testcase testcase="go" final-command="type(foo)"/> + <!-- <xpath-ui-element name="userName" xpath="//fieldset[./legend/text()='User search']//input[@id='login']" description="user name field"/> unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='firstName']" name="firstName" description="first name field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='lastName']" name="lastName" description="last name field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='email']" name="email" description="email field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='zipCode']" name="zipCode" description="zip code field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='region']" name="region" description="region field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='city']" name="city" description="city field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='country']" name="country" description="country field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='institutionalName']" name="institution" description="institution field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='institutionalUserIdentifier']" name="institutionalIdentifier" description="instutition identifier field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='institutionalEmail']" name="institutionalEmail" description="instutitional email field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='orgUnit']" name="orgUnit" description="organizational unit field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='studySubject']" name="fieldOfStudies" description="field of studies field"/> asa unused --> + + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='Administrator']" name="administrator" description="the administrator checkbox" testcase="go/check(userManagement::content_userSearch_administrator)"/> + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='Author']" name="author" description="the author checkbox" testcase="go/check(userManagement::content_userSearch_author)"/> + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='Group manager']" name="groupManager" description="the group manager checkbox" testcase="go/check(userManagement::content_userSearch_groupManager)"/> + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='User manager']" name="userManager" description="the user manager checkbox" testcase="go/check(userManagement::content_userSearch_userManager)"/> + + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='OLAT/WebDAV password ']" name="olatWebdavPassword" description="the olat/webdav password checkbox" testcase="go/check(userManagement::content_userSearch_olatWebdavPassword)"/> + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@class='b_checkbox' and @value='No authentication']" name="noAuthentication" description="the no authentication checkbox" testcase="go/check(userManagement::content_userSearch_noAuthentication)"/> + <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//select[@name='status']" name="status" description="status dropdown" testcase="go/select(userManagement::content_userSearch_status,Active)"/> + + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='afterDate']" name="createdAfter" description="the created-after field"/> asa unused --> + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@id='beforeDate']" name="createdBefore" description="the created-before field"/> asa unused --> + + <!-- <xpath-ui-element xpath="//fieldset[./legend/text()='User search']//input[@value='Search']" name="search" description="the search button" testcase="go/userManagement::content_userSearch_search"/> unused --> + </pageset> + + <pageset name="createUser" description="create new user form"> + <testcase-macro name="go"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="tabs::userManagement"/> + <selenium command="clickAndWait" target="userManagement::menu_createUser"/> + </testcase-macro> + <default-testcase testcase="go" final-command="type(foo)"/> + + <!-- <xpath-ui-element name="userName" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='User name']//input" description="user name field"/> + <xpath-ui-element name="firstName" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='First name']//input" description="first name field"/> + <xpath-ui-element name="lastName" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Last name']//input" description="last name field"/> + <xpath-ui-element name="email" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='E-mail address']//input" description="email field"/> + <xpath-ui-element name="institution" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Institution']//input" description="institution field"/> + <xpath-ui-element name="institutionalId" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and contains(.//label/text(), 'Institution identifier')]//input" description="institution identifier field"/> + <xpath-ui-element name="institutionalEmail" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Institutional e-mail']//input" description="institutional email field"/> + <xpath-ui-element name="orgUnit" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Organizational unit / study group']//input" description="organizational unit / study group field"/> + <xpath-ui-element name="fieldOfStudies" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Field of studies']//input" description="field of study field"/> + <xpath-ui-element name="password" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Password']//input" description="password field"/> + <xpath-ui-element name="verifyPassword" xpath="//fieldset[./legend/text()='Create new user']//div[@class='b_form_element_wrapper b_clearfix' and .//label/text()='Verify password']//input" description="verify password field"/> unused --> + <xpath-ui-element name="language" xpath="//select[@name='new.form.language_SELBOX']" description="select language"></xpath-ui-element> + <xpath-ui-element name="save" xpath="//fieldset[./legend/text()='Create new user']//button[./span/text()='Save']" description="the save button" testcase="go/userManagement::content_createUser_save"/> + </pageset> + + <pageset name="userdetail" description="the detail settings of a particular user - under user management"> + <testcase-macro name="go"> + <call-macro name="login"/> + <selenium command="clickAndWait" target="tabs::userManagement"/> + <selenium command="clickAndWait" target="userManagement::menu_userManagement"/> + <selenium command="type" target="userManagement::content_userSearch_userName" value="administrator"/> + <selenium command="clickAndWait" target="userManagement::content_userSearch_search"/> + <selenium command="clickAndWait" target="ui=commons::usertable_userlist_selectUserName(nameOfUser=administrator)"/> + </testcase-macro> + <default-testcase testcase="go" final-command="clickAndWait"/> + <xpath-ui-element name="userProfile" xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='User profile']" description="the user profile tab link" testcase="go/userManagement::content_userdetail_systemSettings/userManagement::content_userdetail_userProfile"/> + <xpath-ui-element name="systemSettings" xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='System settings']" description="the system settings tab link"/> + <xpath-ui-element name="changePassword" xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Change password']" description="the change password tab link"/> + <!-- <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Authentications']" name="authentications" description="the authentications tab link"/> asa unused --> + <!-- <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Properties']" name="properties" description="the properties tab link"/> asa unused --> + <!-- <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Rights']" name="rights" description="the rights tab link"/> asa unused --> + <xpath-ui-element name="roles" xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Roles']" description="the roles tab link"/> + <!-- <xpath-ui-element xpath="//div[@class='b_tabbedpane_tabs']//a[./text()='Quota']" name="quota" description="the quota tab link"/> asa unused --> + + <pageset name="changePasswordTab" description="change password tab"> + <xpath-ui-element name="newPassword" xpath="//div[@class='b_form_element_wrapper b_clearfix' and .//text()='New password']//div[@class='b_form_element']//input[@type='password']" description="new password input"/> + <xpath-ui-element name="confirmPassword" xpath="//div[@class='b_form_element_wrapper b_clearfix' and .//text()='Confirm password']//div[@class='b_form_element']//input[@type='password']" description="confirm password input"/> + </pageset> + + <pageset name="roles" description="roles tab"> + <xpath-ui-element name="isUsermanager" xpath="//input[@name='roles' and @value='isUserManager']" description="isUsermanager checkbox"/> + <xpath-ui-element name="isGroupmanager" xpath="//input[@name='roles' and @value='isGroupManager']" description="isGroupmanager checkbox"/> + <xpath-ui-element name="isAuthor" xpath="//input[@name='roles' and @value='isAuthor']" description="isAuthor checkbox"/> + <xpath-ui-element name="isAdmin" xpath="//input[@name='roles' and @value='isAdmin']" description="isAdmin checkbox"/> + <xpath-ui-element name="isLearningResourceManager" xpath="//input[@name='roles' and @value='isInstitutionalResourcemanager']" description="Learning resource manager checkbox"/> + <!-- <xpath-ui-element name="save" xpath="//fieldset[contains(./legend/text(), 'Assign system roles and rights')]//input[@value='Save']" description="the save button"/> unused --> + </pageset> + </pageset> + + <pageset name="importUsers" description="import users links"> + <xpath-ui-element name="startUserImport" xpath="//a[descendant::text()='Start user import ']" description="click start user import"/> + <xpath-ui-element name="fillTextArea" xpath="//fieldset[./legend='User import']//textarea" description="fill text area with the user table"/> + <xpath-ui-element name="next" xpath="//a[@class='b_button b_wizard_button_next']" description="Next button of the import users wizard"/> + <xpath-ui-element name="finish" xpath="//a[@class='b_button b_wizard_button_finish']" description="Finish button of the import users wizard"/> + <xpath-ui-element name="cancel" xpath="//a[@class='b_button b_wizard_button_cancel']" description="cancel link of the import users wizard"/> + <xpath-ui-element name="importWarnIcon" xpath="//span[@class='b_small_icon b_warn_icon']" description="import warn icon"/> + </pageset> + + <pageset name="usersReplayURL" description="replay URL ans AJAX OFF"> + <xpath-ui-element name="userReplayTextArea" xpath="//textarea[@name='bulkuserreplay.tt']" description="user replay text area"></xpath-ui-element> + </pageset> + </pageset> + </pageset> +</ui-map-include> \ No newline at end of file