Une MAJ de sécurité est nécessaire sur notre version actuelle. Elle sera effectuée lundi 02/08 entre 12h30 et 13h. L'interruption de service devrait durer quelques minutes (probablement moins de 5 minutes).

Commit 41b39b93 authored by Mathieu Giraud's avatar Mathieu Giraud
Browse files

Merge branch 'feature-s/server_for_doc_screenshot' into 'dev'

Feature s/server for doc screenshot

See merge request !964
parents 515f3cb1 928efa90
Pipeline #265326 failed with stages
in 7 minutes and 3 seconds
......@@ -13,6 +13,7 @@ stages:
- deploy_review
- test_germlines
- test_functional
- test_cypress_client
- test_tutorial
- test_tutorial_server
- test_shouldvdj
......@@ -25,7 +26,6 @@ stages:
- benchmark
- publish_release
- deploy_prod
# Anchors
.coverage_dependency:
......@@ -58,6 +58,7 @@ include:
- local: '/doc/.gitlab-ci.yml' # Doc
- local: 'algo/.gitlab-ci-compilers.yml' # Stage multiple_tests
- local: 'algo/.gitlab-ci.yml' # Vidjil-algo pipelines
- local: 'browser/.gitlab-ci.yml' # Client pipelines
- template: Code-Quality.gitlab-ci.yml # Code quality
# Algorithm
......@@ -285,7 +286,6 @@ old-chrome-browser-functional-external-chrome:
- legacy
.browser-tutorial:
stage: test_tutorial
retry: 2
......@@ -629,3 +629,4 @@ stop_deploy_review_server:
only:
- /^feature-.*s.*\/.*$/
- /^hotfix-.*s.*\/.*$/
......@@ -55,6 +55,28 @@ functional_server:
headless_server:
$(MAKE) -C server headless
###############################
### Browser tests WITH CYPRESS
build_cypress_image:
docker build ./docker/ci -t "vidjilci/cypress_with_browsers:latest"
functional_browser_cypress_open:
# Need to create a symbolic link; but allow to directly see result
# Usefull for fast debugging; allow to launch script one by one
cypress open --env workdir=$(PWD),host=local
functional_browser_cypress:
docker run \
-v $(PWD)/browser/test/cypress:/app/cypress \
-v $(PWD)/browser/test/data/:/app/cypress/fixtures/data/ \
-v $(PWD)/doc/:/app/cypress/fixtures/doc/ \
-v $(PWD):/app/vidjil \
-v "$(PWD)/docker/ci/cypress_script.bash":"/app/script.bash" \
-v "$(PWD)/docker/ci/cypress.json":"/app/cypress.json" \
--env BROWSER=electron --env HOST=local "vidjilci/cypress_with_browsers:latest" bash script.bash
###############################
tutorial-test.rb:
$(MAKE) -C doc/tutorial tutorial-test.rb
###
......
.test_cypress_base:
stage: test_cypress_client
script:
- docker pull "vidjilci/cypress_with_browsers:latest"
- cd browser/
- make icons
- cd ..
- make -C doc analysis-example || true
# Cypress
- echo -e "Run cypress with browser; $CYPRESS_PATH"
- >
docker run
-v $PWD/$CYPRESS_PATH:/app/cypress
-v $PWD/browser/test/data:/app/cypress/fixtures/data
-v $PWD/doc:/app/cypress/fixtures/doc
-v $PWD:/app/vidjil
-v "$PWD/docker/ci/cypress.json":"/app/cypress.json"
-v "$PWD/docker/ci/cypress_script.bash":"/app/script.bash"
--env BROWSER=$BROWSER
--env HOST=$HOST
--env PROJECT=$PROJECT
--env CI_PASSWORD_TEST=$CI_PASSWORD_TEST
--network="host"
"vidjilci/cypress_with_browsers:latest" bash script.bash
variables:
BROWSER: electron
CYPRESS_PATH: browser/test/cypress
HOST: local
artifacts:
reports:
junit: $CYPRESS_PATH/reports/test-cypress-*.xml
paths:
- $CYPRESS_PATH
expire_in: 7 day
when: always
tags:
- docker
## cypress client
client_firefox_legacy:
extends:
- .test_cypress_base
variables:
BROWSER: browsers/firefox_legacy/firefox
client_firefox_latest:
extends:
- .test_cypress_base
variables:
BROWSER: browsers/firefox_latest/firefox
client_chrome_latest:
extends:
- .test_cypress_base
variables:
BROWSER: browsers/chrome_latest/chrome
client_chrome_legacy:
extends:
- .test_cypress_base
variables:
BROWSER: browsers/chrome_legacy/chrome
......@@ -282,6 +282,9 @@ List.prototype = {
sort.id = "list_sort_select"
sort.className = "list_sort_select"
sort.onchange = function() {
self.update_is_pending = true
self.m.updateIcon()
self.sort_option[this.value]()
self.sort_option_selected = this.value
// close the lock
......@@ -290,6 +293,8 @@ List.prototype = {
var div = document.getElementById("div_sortLock")
div.className = "icon-lock-1 list_lock_on"
div.title = "Release sort as '" + self.sort_option_selected +"' on sample " + self.m.getStrTime(self.m.t, "names")
self.update_is_pending = false
self.m.updateIcon()
}
for (var key in this.sort_option) {
......
......@@ -1354,6 +1354,9 @@ changeAlleleNotation: function(alleleNotation, update, save) {
if (this.waiting_screen_is_on)
return true;
if (this.loading_is_pending == true)
return true;
return false;
},
......
......@@ -103,7 +103,7 @@ Model_loader.prototype = {
var self = this;
console.log("load()");
this.loading_is_pending = true
if (document.getElementById(id)
.files.length === 0) {
return;
......@@ -127,6 +127,7 @@ Model_loader.prototype = {
self.check_export_monitor()
self.file_source = "local";
}
this.loading_is_pending = false
},
......
/home/florian/vidjil_issues/vidjil_raw_2/browser/test/data
\ No newline at end of file
/home/florian/vidjil_issues/vidjil_raw_2/doc
\ No newline at end of file
{
"local": {"id":61, "config":2},
"review": {"id":18, "config":2},
"app": {"id":61, "config":2}
}
/// <reference types="cypress" />
var localhost = true
console.log( Cypress.env('workdir') )
var url = "./"+ Cypress.env('workdir')+"/browser/index.html"
console.log( url )
describe('Actions v1', function () {
beforeEach(function () {
cy.setBrowser(url)
})
it('Open a simple vidjil file', function() {
cy.openAnalysis("doc/analysis-example2.vidjil")
cy.get('#list_clones').children().should('have.length', 8)
cy.get('#listElem_5 > .nameBox').should('have.text', "clone_cluster1")
cy.get('#listElem_5 > .axisBox > .sizeBox').should('have.text', "0.408%")
return
})
it('Open a vidjil file + analysis', function() {
cy.openAnalysis("doc/analysis-example2.vidjil", "doc/analysis-example2.analysis")
cy.get('#listElem_5 > .nameBox').should('have.text', "clone_cluster1")
// second sample open with analysis, so size is smaller
cy.get('#listElem_5 > .axisBox > .sizeBox').should('have.text', "0.014%")
cy.get('#listElem_6 > .nameBox').should('not.visible');
return
})
it('test_00_list_clones', function() {
cy.openAnalysis("doc/analysis-example2.vidjil", "doc/analysis-example2.analysis")
// # change current sample to start on sample 0 (second in loaded order)
// cy.get("body").type("{rightarrow}")
cy.update_icon()
// declare variables
var lock = cy.get('#div_sortLock')
var listClone = cy.get('#list_clones')
// tester la presence du lock
cy.get('#div_sortLock')
.should('have.class', "icon-lock-1 list_lock_on")
.and('have.attr', 'title')
.and('include', "Release sort as '-' on sample diag")
cy.get('#list_clones').children().eq(0)
.should("contain", "Main ALL clone")
cy.get('#list_clones').children().eq(1)
.should("contain", "TRG smaller clone")
// change order by 'size'
cy.get('#list_sort_select')
.select('size')
.should('have.value', 'size')
cy.get('#list_sort_select')
.should('not.have.value', '-')
cy.update_icon()
// cy.waitForUpdates()
cy.get('#div_sortLock').should('have.class', "icon-lock-1 list_lock_on")
.and('have.attr', 'title')
.and('include', "Release sort as 'size' on sample fu1")
cy.get('#list_clones').children().eq(0)
.should("contain", "TRG smaller clone")
cy.get('#list_clones').children().eq(1)
.should("contain", "Main ALL clone")
// Ex test_01_xxx
cy.get("body").type("{rightarrow}")
cy.update_icon()
cy.get('#list_clones').children().eq(0)
.should("contain", "TRG smaller clone")
cy.get('#div_sortLock').should('have.class', "icon-lock-1 list_lock_on")
.and('have.attr', 'title')
.and('include', "Release sort as 'size' on sample fu1")
cy.get('#list').screenshot('/panel_list_v2')
})
})
// ***********************************************
// import 'cypress-wait-until';
var lil_l3 = {"app": {"id":61, "config":2}, "localhost": {"id":3241, "config":25}}
Cypress.Commands.add('close_disclamer', () => {
cy.get("div.popup_container", { timeout: 10000 })
.should('be.visible')
.and('contain', 'The Vidjil Team')
.get('.center > button')
.click()
})
Cypress.Commands.add('close_tips', () => {
cy.get('.tip_1')
.should('be.visible')
.and('contain', 'Tip:')
.get('.tip_1 > .icon-cancel')
.click()
})
Cypress.Commands.add('setBrowser', (url) => {
cy.visit(url)
// close disclamer only for direct opening of the index.html file
if (url.indexOf("index.html") != -1){
cy.close_disclamer()
cy.close_tips()
}
})
Cypress.Commands.add('open_menu_import', () => {
cy.get('#demo_file_menu').click()
})
Cypress.Commands.add("openAnalysis", (file_vidjil, file_analysis) => {
cy.open_menu_import()
cy.get('#import_data_anchor').click()
cy.log(`file_vidjil: ${file_vidjil}`)
cy.log(`file_analysis: ${file_analysis}`)
// Upload vidjil file
cy.get("input[id=upload_json]")
.then(($btn) => { cy.get("input[id=upload_json]").uploadFile(file_vidjil); })
// Upload analysis file (if given)
if (file_analysis != undefined) {
cy.get("input[id=upload_pref]")
.then(($btn) => {cy.get("input[id=upload_pref]").uploadFile(file_analysis); })
}
// Launch loading
cy.get("button[id=start_import_json]")
.click();
// Wait the end of the loading (async)
cy.update_icon()
})
/**
* Allow to wait for update icon to be not visible
*/
Cypress.Commands.add("update_icon", () => {
cy.get('#updateIcon').should("not.visible")
})
Cypress.Commands.add('getById', (input) => {
cy.get(`[data-cy=${input}]`)
})
Cypress.Commands.add('isDbPageVisible', () => {
// return cy.get('.db_div').should("be.visible")
cy.get('.db_div').then($button => {
if ($button.is(':visible')){
return true
} else {
return false
}
})
})
Cypress.Commands.add('goToDBPage', () => {
cy.isDbPageVisible().then((val) => {
console.log( val )
if (val == false){
cy.get('#db_menu').trigger('mouseover')
.contains('open list')
.should('be.visible')
.click()
cy.get('.db_div')
.should('be.visible')
}
})
})
Cypress.Commands.add('goToPatientPage', () => {
cy.goToDBPage().then(() => {
cy.get('#db_menu > .patient_token')
.click()
cy.get('.db_div')
.should('contain', ' + new patients ')
})
})
Cypress.Commands.add('goToRunPage', () => {
cy.goToDBPage().then(() => {
cy.get('#db_menu > .run_token')
.click()
cy.get('.db_div')
.should('contain', ' + new runs ')
})
})
\ No newline at end of file
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './tools'
import './login'
import './commands'
import './db_pages'
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from failing the test
if (resizeObserverLoopErrRe.test(err.message)) { return false }
return false
})
beforeEach(() => {
cy.on("window:before:load", (win) => {
cy.spy(win.console, "log");
})
})
\ No newline at end of file
Cypress.Commands.add('login', (host) => {
if (host=="local"){
cy.visit('https://localhost/browser')
cy.waitForUpdates()
// log in
cy.get('#auth_user_email')
.type('plop@plop.com')
cy.get('#auth_user_password')
.type('foobartest')
cy.get('#submit_record__row > .w2p_fw > input').click()
cy.waitForUpdates()
} else if (host=="review"){
cy.visit('https://localhost/browser')
cy.waitForUpdates()
// log in
cy.get('#auth_user_email')
.type('test@vidjil.org')
cy.get('#auth_user_password')
.type(Cypress.env('CI_PASSWORD_TEST'))
cy.get('#submit_record__row > .w2p_fw > input').click()
cy.waitForUpdates()
} else if (host=="app"){
cy.visit('https://app.vidjil.org/')
cy.waitForUpdates()
// log in
cy.get('#auth_user_email')
.type('demo@vidjil.org')
cy.get('#auth_user_password')
.type('demo')
// .type('demo')
cy.get('#submit_record__row > .w2p_fw > input').click()
cy.waitForUpdates()
}
cy.verifyLogin()
})
Cypress.Commands.add('verifyLogin', (host) => {
cy.get('body').should('not.contain', 'You can request an account')
cy.get('body').should('contain', 'logout')
})
Cypress.Commands.add('waitForUpdates', () => {
cy.wait(1000)
})
//
Cypress.Commands.add("uploadFile",
{ prevSubject: true },
(subject, fileName) => {
cy.fixture(fileName).then(content => {
const el = subject[0];
const testFile = new File([content], fileName);
const dataTransfer = new window.DataTransfer();
dataTransfer.items.add(testFile);
el.files = dataTransfer.files;
cy.wrap(subject).trigger("change", { force: true });
});
}
);
......@@ -614,3 +614,67 @@ webpage.
If you have to launch `irb` on a remote server without X (only using `Xvfb`)
you may be interested to use the [redirection over SSH](https://en.wikipedia.org/wiki/Xvfb#Remote_control_over_SSH).
### Functional with cypress (release candidate)
To avoid `Watir` limitation on latest versions of browsers, we adopt [Cypress](https://docs.cypress.io/guides/overview/why-cypress#In-a-nutshell).
The testing pipeline is build on a docker image which include legacy and latest version of chrome and firefox (as at june 2021).
We will progressivly convert Watir tests on Cypress.
1. Instalation
The docker image to used can be build from local repository, or downloaded from dockerhub repository.
Docker should be installed for these tests.
1. Local build
```bash
docker build ./docker/ci -t "vidjilci/cypress_with_browsers:latest"
```
2. Dockerhub pull
```bash
docker pull "vidjilci/cypress_with_browsers:latest"
```
2. Usage
The default usage of cypress pipeline use docker image and is launch in headless mode.
See the makefile rule `functional_browser_cypress`.
This rule launch the next command:
```bash
docker run \
-v $(PWD)/browser/test/cypress:/app/cypress \
-v $(PWD)/browser/test/data/:/app/cypress/fixtures/data/ \
-v $(PWD)/doc/:/app/cypress/fixtures/doc/ \
-v $(PWD):/app/vidjil \
-v "$(PWD)/docker/ci/cypress_script.bash":"/app/script.bash" \
-v "$(PWD)/docker/ci/cypress.json":"/app/cypress.json" \
--env BROWSER=electron --env HOST=local "vidjilci/cypress_with_browsers:latest" bash script.bash
```
Various local volumes are mounted for these tests.
Tests scripts are located in `browser/test/cypress`.
In this directory you can find scripts of `support` (shared functions), `fixtures` (datas used during tests) and finally `integration` (testing scripts).
3. Interactive mode
For interactive mode, Cypress should be installed on local computer and some symbolic links should be created.
More informations will be provided next.
4. Troubleshooting
1. Xvfb error
Sometime during developpement, the cypress pipeline can failed. In some case, the XVDB server can still open after test ending and the docker image still open.
In this case, stop the docker container.
```bash
docker ps
docker stop $container_id
```
2. Right error on produced files (report and screenshot)
Files produced by cypress docker are made with root right. These files should be deleted with root privilege.
```bash
sudo rm -r browser/test/cypress/report browser/test/cypress/screenshots
```
\ No newline at end of file
FROM ubuntu:20.04
LABEL version="0.1"
LABEL description="An Cypress based docker image which comes with cypress pipeline and various browsers version."
WORKDIR /app
COPY cypress.json .
COPY package.json .
COPY cypress_script.bash script.bash
##################################
### Update and install ressources
##################################
ENV DEBIAN_FRONTEND="noninteractive" TZ="Europe/Paris"
RUN apt-get update && apt-get install --no-install-recommends --no-install-suggests -y -q npm libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb wget bzip2 tar unzip nano cu