Merge branch 'master' into release/rework-css
This commit is contained in:
		
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,11 @@ | ||||
| **/node_modules | ||||
| **/config.json | ||||
| config.json | ||||
| .DS_Store | ||||
| *.iml | ||||
| *.swp | ||||
| dist | ||||
| .DS_Store | ||||
| cypress/screenshots | ||||
| cypress/videos | ||||
| cache | ||||
| .npm | ||||
| .DS_Store | ||||
|  | ||||
| @ -1,13 +1,56 @@ | ||||
| image: node:11 | ||||
|  | ||||
| # workflow | ||||
| stages: | ||||
|  - build | ||||
|  - test | ||||
|  - integration | ||||
|  - acceptance | ||||
|  - release | ||||
|  - deployment | ||||
|  | ||||
| # default image for jobs | ||||
| default: | ||||
|   image: node:11 | ||||
|  | ||||
| # cache modules between jobs | ||||
| cache: | ||||
|   key: ${CI_COMMIT_REF_SLUG} | ||||
|   paths: | ||||
|     - .npm/ | ||||
|  | ||||
| ## BUILD ## | ||||
|  | ||||
| build: | ||||
|   stage: build | ||||
|   before_script: | ||||
|     - npm ci --cache .npm --prefer-offline --only=production | ||||
|   script: | ||||
|     - cp config.sample.json config.json | ||||
|     - npm run build | ||||
|   artifacts: | ||||
|     when: on_success | ||||
|     expire_in: 1 day | ||||
|     paths: | ||||
|       - dist/ | ||||
|   tags: | ||||
|     - test | ||||
|  | ||||
| ## TESTING ## | ||||
|  | ||||
| test:e2e: | ||||
|   stage: test | ||||
|   image: cypress/included:4.5.0 | ||||
|   services: | ||||
|     - name: ${CI_REGISTRY_IMAGE}/server:0.1 | ||||
|   before_script: | ||||
|     # install missing dependencies | ||||
|     - npm install -g sirv-cli | ||||
|      # making sure the process is orphan | ||||
|     - sirv dist --port 3000 > /dev/null 2>&1 & | ||||
|   script: | ||||
|     - cypress run -e CYPRESS_baseUrl=http://localhost:3000 | ||||
|   tags: | ||||
|     - test | ||||
|  | ||||
| ## VALIDATION ## | ||||
|  | ||||
| test1: | ||||
|  | ||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
								
							| @ -221,6 +221,34 @@ On `config.json`: | ||||
|   } | ||||
| ``` | ||||
|  | ||||
| ## Use with docker | ||||
|  | ||||
| ### Multi services | ||||
|  | ||||
| Run with a local binding on localhost: | ||||
|  | ||||
| ```bash | ||||
| docker-compose build | ||||
| docker-compose up -d client server | ||||
| ``` | ||||
|  | ||||
| Use in CI context: | ||||
|  | ||||
| ```bash | ||||
| docker-compose -f docker-compose.yml build | ||||
| docker-compose -f docker-compose.yml up -d client server | ||||
| docker-compose -f docker-compose.yml run --rm e2e | ||||
| ``` | ||||
|  | ||||
| Build and push the server to registry: | ||||
|  | ||||
| ```bash | ||||
| docker build -f docker/djangoldp.docker --build-arg serve="http://localhost:8000" -t registry.startinblox.com/applications/hubl/server:0.1 . | ||||
| docker push registry.startinblox.com/applications/hubl/server:0.1 | ||||
| ``` | ||||
|  | ||||
| Note: within a Kubernetes pod all services are bound to `localhost`. | ||||
|  | ||||
| ## Built With | ||||
|  | ||||
| * [Sib-Core](https://git.startinblox.com/framework/sib-core/) - An awesome new framework! | ||||
|  | ||||
| @ -3,8 +3,8 @@ | ||||
|   "authority": "http://localhost:8000/", | ||||
|   "authorityName": "djangoldp-server-name", | ||||
|   "endpoints": { | ||||
|     "groups": "http://localhost:8000/groups/", | ||||
|     "skills": "http://localhost:8000/skills/", | ||||
|     "users": "http://localhost:8000/users/", | ||||
|     "groups": "http://localhost:8000/groups/" | ||||
|     "users": "http://localhost:8000/users/" | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										7
									
								
								cypress.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cypress.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| { | ||||
|     "baseUrl": "http://127.0.0.1:3000", | ||||
|     "defaultCommandTimeout": 60000, | ||||
|     "chromeWebSecurity": false, | ||||
|     "viewportWidth": 1920, | ||||
|     "viewportHeight": 1080 | ||||
| } | ||||
							
								
								
									
										5
									
								
								cypress/fixtures/example.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								cypress/fixtures/example.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|   "name": "Using fixtures to represent data", | ||||
|   "email": "hello@cypress.io", | ||||
|   "body": "Fixtures are a great way to mock data for responses to routes" | ||||
| } | ||||
							
								
								
									
										108
									
								
								cypress/integration/tests.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								cypress/integration/tests.spec.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| /// <reference types="Cypress" /> | ||||
|  | ||||
|  | ||||
| context('Browser testing', () => { | ||||
|     before(() => { | ||||
|       cy.clearLocalStorage({ domain: null}); | ||||
|       cy.clearCookies({ domain: null }); | ||||
|     }); | ||||
|     it('visit the homepage', () => { | ||||
|       cy.visit('/'); | ||||
|     }); | ||||
|     it('should await for an user login', () => { | ||||
|       cy.location().should((loc) => { | ||||
|         expect(loc.pathname).to.eq('/auth/login/'); | ||||
|       }); | ||||
|     }); | ||||
|     describe('Login process', () => { | ||||
|       it('should write "admin" on username field and "password" on password field', () => { | ||||
|         cy.get('#id_username').type('admin'); | ||||
|         cy.get('#id_username').should('have.value', 'admin'); | ||||
|         cy.get('#id_password').type('password'); | ||||
|         cy.get('#id_password').should('have.value', 'password'); | ||||
|       }); | ||||
|       it('should click on login button', () => { | ||||
|         cy.get(':nth-child(1) > .flex-column > [type="submit"]').click(); | ||||
|       }); | ||||
|       it('should provide an error, username and password mismatch.', () => { | ||||
|         cy.get('.error').should('contain.text', 'Ton nom d\'utilisateur et ton mot de passe ne correspondent pas. Réessaye.') | ||||
|       }); | ||||
|       it('should write "admin" on password field then press the login button', () => { | ||||
|         cy.get('#id_password').type('admin'); | ||||
|         cy.get('#id_password').should('have.value', 'admin'); | ||||
|         cy.get(':nth-child(1) > .flex-column > [type="submit"]').click(); | ||||
|       }); | ||||
|       it('should ask for user permission to access their datas.', () => { | ||||
|         cy.location().should((loc) => { | ||||
|           expect(loc.pathname).to.eq('/authorize') | ||||
|         }); | ||||
|         cy.get('.accept-button').click(); | ||||
|       }); | ||||
| //      it('should redirect the user to the app.', () => { | ||||
| //        cy.get('.accept-button').click(); | ||||
| //        cy.location().should((loc) => { | ||||
| //          expect(loc.protocol + "//" + loc.host).to.eq(Cypress.config().baseUrl); | ||||
| //          expect(loc.pathname).to.eq('/'); | ||||
| //        }); | ||||
| //      }); | ||||
| //    }); | ||||
| //    describe('Main interface', () => { | ||||
| //      // it('should show my name on top right', () => { | ||||
| //      //   cy.get('sib-display-value').contains('Admin'); | ||||
| //      // }); | ||||
| //      it('should show my username on the left menu', () => { | ||||
| //        cy.get('[fields="username, badge"][data-src="http://localhost:8000/users/admin/"] > :nth-child(1) > sib-display-div > div').contains('admin'); | ||||
| //      }); | ||||
| //      it('should open a chat with myself', () => { | ||||
| //        cy.get('[fields="username, badge"][data-src="http://localhost:8000/users/admin/"] > :nth-child(1) > sib-display-div > div').click(); | ||||
| //        cy.get('.name').contains('admin'); | ||||
| //      }); | ||||
| //      it('should not work, because I have no Prosody configured', () => { | ||||
| //        cy.get('.content-box > .chat-view > sib-chat').should('be.empty'); | ||||
| //      }); | ||||
| //      describe('Circles', () => { | ||||
| //        it('should navigate the Administration from left menu', () => { | ||||
| //          cy.get('.create > sib-link').click(); | ||||
| //          cy.get('#admin-circles > .content-box > .content-box__header > .without-margin').contains('Administration'); | ||||
| //          cy.get('#admin-circle-list > .content-box__info > .admin-header > .admin-header__title').contains('Circles'); | ||||
| //        }); | ||||
| //        it('should navigate to Circle creation', () => { | ||||
| //          cy.get('#admin-circle-list > .content-box__info > .admin-header > .button').click(); | ||||
| //          cy.location().should((loc) => { | ||||
| //            expect(loc.pathname).to.contain('admin-circle-create'); | ||||
| //          }); | ||||
| //        }); | ||||
| //        var name = new Uint32Array(1); | ||||
| //        crypto.getRandomValues(name); | ||||
| //        name = "Test Circle " + name; | ||||
| //        it('should allow Circle Creation', () => { | ||||
| //          cy.get('form > sib-form-label-text[name="name"] > label > input').type(name); | ||||
| //          cy.get('.content-box__info > sib-form > form > sib-form-label-text[name="description"] > label > input').type('With a great description!'); | ||||
| //          cy.get('#admin-circle-create > .content-box__info > sib-form > form > [type="submit"]').click(); | ||||
| //          cy.get('#admin-circle-list > div > div.table > sib-display').contains(name); | ||||
| //        }); | ||||
| //        it('should open the circle information page', () => { | ||||
| //          cy.screenshot(); | ||||
| //          cy.get('#navbar-router').contains(name).click(); | ||||
| //          cy.get('[name="circle-information"] > li').click(); | ||||
| //        }); | ||||
| //        it('should delete the circle', () => { | ||||
| //          cy.get('.box-button > sib-ac-checker > .button').click(); | ||||
| //          cy.get('#navbar-router').should('not.contain', name); | ||||
| //        }); | ||||
| //      }); | ||||
| //    }); | ||||
| //    describe('Logout process', () => { | ||||
| //      it('should properly log out the user', () => { | ||||
| //        cy.get('#user-controls__profile > div').click(); | ||||
| //        cy.get('#user-controls__panel > nav > button').click(); | ||||
| //        // Dirty fix for logout, targeting logout button is not enough. | ||||
| //        cy.clearLocalStorage({ domain: null }); | ||||
| //        cy.clearCookies({ domain: null }); | ||||
| //        cy.location().should((loc) => { | ||||
| //          expect(loc.pathname).to.eq('/auth/login/'); | ||||
| //        }); | ||||
| //      }); | ||||
|     }); | ||||
|   }); | ||||
|    | ||||
							
								
								
									
										20
									
								
								cypress/plugins/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								cypress/plugins/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| /// <reference types="cypress" /> | ||||
| // *********************************************************** | ||||
| // This example plugins/index.js can be used to load plugins | ||||
| // | ||||
| // You can change the location of this file or turn off loading | ||||
| // the plugins file with the 'pluginsFile' configuration option. | ||||
| // | ||||
| // You can read more here: | ||||
| // https://on.cypress.io/plugins-guide | ||||
| // *********************************************************** | ||||
|  | ||||
| // This function is called when a project is opened or re-opened (e.g. due to | ||||
| // the project's config changing) | ||||
|  | ||||
| /** | ||||
|  * @type {Cypress.PluginConfig} | ||||
|  */ | ||||
| module.exports = (on, config) => { | ||||
| //    require('cypress-terminal-report').installPlugin(on); | ||||
| }; | ||||
							
								
								
									
										25
									
								
								cypress/support/commands.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								cypress/support/commands.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| // *********************************************** | ||||
| // This example commands.js shows you how to | ||||
| // create various custom commands and overwrite | ||||
| // existing commands. | ||||
| // | ||||
| // For more comprehensive examples of custom | ||||
| // commands please read more here: | ||||
| // https://on.cypress.io/custom-commands | ||||
| // *********************************************** | ||||
| // | ||||
| // | ||||
| // -- This is a parent command -- | ||||
| // Cypress.Commands.add("login", (email, password) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This is a child command -- | ||||
| // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This is a dual command -- | ||||
| // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This will overwrite an existing command -- | ||||
| // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) | ||||
							
								
								
									
										30
									
								
								cypress/support/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								cypress/support/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| // *********************************************************** | ||||
| // 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 './commands' | ||||
|  | ||||
| //require('cypress-terminal-report').installSupport(); | ||||
|  | ||||
| // Alternatively you can use CommonJS syntax: | ||||
| // require('./commands') | ||||
| Cypress.on('uncaught:exception', (err, runnable) => { | ||||
|     // returning false here prevents Cypress from | ||||
|     // failing the test | ||||
|     console.log('Cypress detected uncaught exception', err); | ||||
|     return false; | ||||
| }); | ||||
|  | ||||
| Cypress.on('fail', () => Cypress.runner.abort()) | ||||
							
								
								
									
										18
									
								
								docker/config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								docker/config.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
|   "xmpp": "https://jabber.happy-dev.fr/http-bind/", | ||||
|   "authority": "$SERVER", | ||||
|   "authorityName": "djangoldp-server-name", | ||||
|   "endpoints": { | ||||
|     "get": { | ||||
|       "circles": "$SERVER/circles/", | ||||
|       "groups": "$SERVER/groups/", | ||||
|       "users": "$SERVER/users/" | ||||
|     }, | ||||
|     "post": { | ||||
|       "circles": "$SERVER/circles/", | ||||
|       "groups": "$SERVER/groups/", | ||||
|       "users": "$SERVER/users/" | ||||
|     } | ||||
|   }, | ||||
|   "analytics": [] | ||||
| } | ||||
							
								
								
									
										26
									
								
								docker/djangoldp.docker
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								docker/djangoldp.docker
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| FROM python:3.6 | ||||
| LABEL maintainer="Plup <plup@plup.io>" | ||||
|  | ||||
| # get server address | ||||
| ARG serve | ||||
|  | ||||
| # fix bug in manager install | ||||
| ENV PATH="/root/.local/bin:${PATH}" | ||||
|  | ||||
| # install a LDP server with required functions | ||||
| WORKDIR /app | ||||
| RUN pip install git+https://git.startinblox.com/djangoldp-packages/server-manager.git | ||||
| RUN sib startproject sibserver | ||||
| COPY docker/packages.yml /app/sibserver/ | ||||
| RUN sed -i 's#SERVER#'"${serve:-http://localhost:8000}"'#' /app/sibserver/packages.yml | ||||
| RUN cd /app/sibserver && sib install server | ||||
|  | ||||
| # fix invalid HTTP_HOST | ||||
| RUN sed -i 's/ALLOWED_HOSTS\s=\s\[\]/ALLOWED_HOSTS=\["\*"\]/' /app/sibserver/server/settings.py | ||||
|  | ||||
| # run the dev server | ||||
| EXPOSE 8000 | ||||
| ENTRYPOINT ["python", "/app/sibserver/manage.py"] | ||||
| CMD ["runserver", "0.0.0.0:8000"] | ||||
|  | ||||
| # vim: ft=dockerfile: | ||||
							
								
								
									
										15
									
								
								docker/docker-compose.override.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								docker/docker-compose.override.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| --- | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|  | ||||
|   front: | ||||
|     environment: | ||||
|       - SERVER=http://127.0.0.1 | ||||
|     ports: | ||||
|       - 80:80 | ||||
|  | ||||
|   server: | ||||
|     build: | ||||
|       args: | ||||
|         serve: http://127.0.0.1 | ||||
							
								
								
									
										39
									
								
								docker/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								docker/docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| --- | ||||
| version: '3' | ||||
|  | ||||
| services: | ||||
|  | ||||
|   front: | ||||
|     build: | ||||
|       context: ../ | ||||
|       dockerfile: docker/front.docker | ||||
|     environment: | ||||
|         - SERVER=http://server.org:8000 | ||||
|     networks: | ||||
|       - web | ||||
|  | ||||
|   server: | ||||
|     build: | ||||
|       context: ../ | ||||
|       dockerfile: docker/djangoldp.docker | ||||
|       args: | ||||
|         serve: http://server.org:8000 | ||||
|     networks: | ||||
|       web: | ||||
|         aliases: | ||||
|           - server.org | ||||
|       db: | ||||
|  | ||||
|   e2e: | ||||
|     image: cypress/included:4.3.0 | ||||
|     environment: | ||||
|       - CYPRESS_baseUrl=https://front | ||||
|     volumes: | ||||
|       - ../cypress:/cypress | ||||
|       - ../cypress.json:/cypress.json | ||||
|     networks: | ||||
|       - web | ||||
|  | ||||
| networks: | ||||
|   web: | ||||
|   db: | ||||
							
								
								
									
										37
									
								
								docker/front.docker
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								docker/front.docker
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| FROM node:12 AS builder | ||||
| LABEL maintainer="Plup <plup@plup.io>" | ||||
|  | ||||
| # install dependencies | ||||
| WORKDIR /build | ||||
| ADD package.json package-lock.json ./ | ||||
| ADD src/ src/ | ||||
| RUN npm install --only=production | ||||
|  | ||||
| # build the app | ||||
| ADD docker/config.json . | ||||
| RUN npm run build | ||||
|  | ||||
| # change index to template | ||||
| RUN mv /build/dist/index.html /build/dist/index.tpl | ||||
|  | ||||
| # generate a self signed certificate | ||||
| RUN openssl req -x509 -newkey rsa:4096 -keyout /tmp/key.pem -out /tmp/cert.pem -days 365 -nodes -subj '/CN=localhost' | ||||
|  | ||||
| # serve | ||||
| FROM nginx:latest | ||||
| COPY --from=builder /build/dist /var/www | ||||
| COPY --from=builder /tmp/*.pem /etc/nginx/ | ||||
| WORKDIR /var/www | ||||
|  | ||||
| # get specific config | ||||
| COPY docker/nginx.conf /etc/nginx/conf.d/default.conf | ||||
| EXPOSE 443 | ||||
|  | ||||
| # get server address | ||||
| ENV SERVER http://localhost:8000 | ||||
|  | ||||
| # replace addresses at runtime | ||||
| CMD /bin/bash -c "envsubst '\$SERVER' < index.tpl > index.html && \ | ||||
|     exec nginx -g 'daemon off;'" | ||||
|  | ||||
| # vim: ft=dockerfile: | ||||
							
								
								
									
										9
									
								
								docker/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								docker/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| server { | ||||
|     listen 443 ssl default_server; | ||||
|     root /var/www/; | ||||
|  | ||||
|     ssl_certificate     /etc/nginx/cert.pem; | ||||
|     ssl_certificate_key /etc/nginx/key.pem; | ||||
|  | ||||
|     try_files $uri $uri/ index.html =404; | ||||
| } | ||||
							
								
								
									
										27
									
								
								docker/packages.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								docker/packages.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| ldppackages: | ||||
|   djangoldp_dashboard: djangoldp_dashboard | ||||
|   djangoldp_account: djangoldp_account | ||||
|   djangoldp_circle: djangoldp_circle | ||||
|   djangoldp_notification: djangoldp_notification | ||||
|   djangoldp_profile: djangoldp_profile | ||||
|   djangoldp_project: djangoldp_project | ||||
|   oidc_provider: 'git+https://github.com/jblemee/django-oidc-provider.git@develop' | ||||
|  | ||||
| server: | ||||
|   site_url: SERVER | ||||
|   allowed_hosts: | ||||
|     - '*' | ||||
|   db_host: database | ||||
|   db_name: postgres | ||||
|   db_user: postgres | ||||
|   db_pass: postgres | ||||
|   smtp_host: | ||||
|   smtp_user: | ||||
|   smtp_pass: | ||||
|   admin_email: test@startinblox.com | ||||
|   admin_name: admin | ||||
|   admin_pass: admin | ||||
|   xmpp_url: https://jabber.happy-dev.fr | ||||
|   jabber_host: 'none' | ||||
|   default_client: SERVER | ||||
|   registration_open: True | ||||
							
								
								
									
										1157
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1157
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							| @ -17,7 +17,11 @@ | ||||
|     "watch": "run-p copy:* watch:* serve", | ||||
|     "watch:css": "npm run build:css && npm run build:css -- -w", | ||||
|     "watch:js": "babel --watch \"src/scripts/*.js\" -o dist/scripts/index.js", | ||||
|     "watch:pug": "pug --watch src/index.pug -o dist/ --obj config.json" | ||||
|     "watch:pug": "pug --watch src/index.pug -o dist/ --obj config.json", | ||||
|     "cypress:open": "cypress open", | ||||
|     "cypress:verify": "cypress verify", | ||||
|     "cypress:info": "cypress info", | ||||
|     "test": "cypress run" | ||||
|   }, | ||||
|   "release": { | ||||
|     "branches": [ | ||||
| @ -59,5 +63,9 @@ | ||||
|     "pug": "^2.0.4", | ||||
|     "pug-cli": "^1.0.0-alpha6", | ||||
|     "pushstate-server": "^3.1.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "cypress": "^4.5.0", | ||||
|     "cypress-terminal-report": "^1.2.1" | ||||
|   } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user