diff --git a/.travis.yml b/.travis.yml index cb5d86c..2c24468 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,7 @@ services: - postgresql before_install: - - # start your web application and listen on `localhost` - - google-chrome-stable --headless --disable-gpu --remote-debugging-port=5000 http://localhost & + - nvm install --lts cache: directories: @@ -23,22 +22,6 @@ cache: jobs: include: - - stage: "Build the frontend and upload a Docker image" - script: - # Build - - cd front - - npm install - - npm run build - - cd - - # Upload the Docker image - - | - if [ "$TRAVIS_EVENT_TYPE" = "push" ]; then - export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" - make front/travis-docker "tag=$BRANCH--front" || travis_terminate 1 - docker login quay.io -u "$DOCKER_USER" -p "$DOCKER_PASS" - docker push "quay.io/aelve/guide:$BRANCH--front" - fi - - stage: "Build the backend and upload a Docker image" before_script: - sudo apt-get install -y libgmp-dev @@ -97,10 +80,68 @@ jobs: exit 1 fi before_cache: - - rm -rf $HOME/.stack/programs # GHC is faster to install than to cache + - rm -rf $HOME/.stack/programs # GHC is faster to install than to cache + + - stage: "Build the frontend and upload a Docker image, test frontend" + - name: "Build the frontend and upload a Docker image" + script: + # Build + - cd front + - npm install + - npm run build + - cd - + # Upload the Docker image + - | + if [ "$TRAVIS_EVENT_TYPE" = "push" ]; then + export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" + make front/travis-docker "tag=$BRANCH--front" + docker login quay.io -u "$DOCKER_USER" -p "$DOCKER_PASS" + docker push "quay.io/aelve/guide:$BRANCH--front" + fi + + - name: "Test frontend prod desktop" + script: + - node -v + - . ./scripts/ci-functions.sh + - cd front + - npm install + - npm run build + - export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" + - run_back $BRANCH + - API_URL=http://localhost:4400/ npm run test:prod + + - name: "Test frontend dev desktop" + script: + - . ./scripts/ci-functions.sh + - cd front + - npm install + - export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" + - run_back $BRANCH + - API_URL=http://localhost:4400/ npm run test:dev + + - name: "Test frontend prod mobile" + script: + - . ./scripts/ci-functions.sh + - cd front + - npm install + - npm run build + - export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" + - run_back $BRANCH + - API_URL=http://localhost:4400/ npm run test:prod:mobile + + - name: "Test frontend dev mobile" + script: + - . ./scripts/ci-functions.sh + - cd front + - npm install + - export BRANCH="$(echo "$TRAVIS_BRANCH" | tr '/' '-')" + - run_back $BRANCH + - API_URL=http://localhost:4400/ npm run test:dev:mobile + - stage: "Test the backend" before_script: + - google-chrome-stable --headless --dis able-gpu --remote-debugging-port=5000 http://localhost & - sudo apt-get install -y libgmp-dev fluxbox - curl -sSL https://get.haskellstack.org/ | sh # travis_retry works around https://github.com/commercialhaskell/stack/issues/4888 @@ -123,14 +164,7 @@ jobs: - make back/test-db - make back/load-into-postgres before_cache: - - rm -rf $HOME/.stack/programs # GHC is faster to install than to cache - - # - stage: "Test the frontend" - # - sleep 10 - # - fluxbox >/dev/null 2>&1 & - # script: - # # Run testcafe e2e testing - # - npm run test + - rm -rf $HOME/.stack/programs # GHC is faster to install than to cache notifications: slack: diff --git a/front/build/setupProdServer.ts b/front/build/setupProdServer.ts index 5454d21..09b6f9a 100644 --- a/front/build/setupProdServer.ts +++ b/front/build/setupProdServer.ts @@ -2,6 +2,7 @@ import path from 'path' import fs from 'fs' import { createBundleRenderer } from 'vue-server-renderer' // TODO move 'src' prefix to config +// TODO do not copy setupDevServer, webpack configs to builded front // TODO find a way to get rid of ts ignore and still build without errors // @ts-ignore import bundle from '../src/vue-ssr-server-bundle.json' diff --git a/front/client/components/AddCategoryBtn.vue b/front/client/components/AddCategoryBtn.vue new file mode 100644 index 0000000..1d27e99 --- /dev/null +++ b/front/client/components/AddCategoryBtn.vue @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/front/client/components/AddCategoryDialog.vue b/front/client/components/AddCategoryDialog.vue index 74854bb..d4f1b6c 100644 --- a/front/client/components/AddCategoryDialog.vue +++ b/front/client/components/AddCategoryDialog.vue @@ -30,11 +30,13 @@ ref="categoryNameInput" class="mb-3" label="Category name" - data-testid="add-category-dialog_category-name-input" + data-testid="AddCategoryDialog-NameInput" :rules="categoryValidationRules" v-model="categoryName" /> @@ -54,7 +56,7 @@ aria-label="Submit" color="info" class="add-category-submit-btn" - data-testid="add-category-dialog_submit-btn" + data-testid="AddCategoryDialog-SubmitBtn" :disabled="!isValid" @click.native="submit" > @@ -71,25 +73,26 @@ - This group already has categories with the same name: - +
+ This group already has categories with the same name: +
    +
  • + {{ category.title }} +
  • +
+
@@ -118,36 +121,44 @@ export default class AddCategoryDialog extends Vue { categoryValidationRules: Array<(x: string) => boolean | string> = [ (x: string) => !!x || `Category name can't be empty` ] + groupValidationRules: Array<(x: string) => boolean | string> = [ + (x: string) => !!x || `Group can't be empty` + ] isValid: boolean = false isDuplicateConfirmShow: boolean = false + sameNameCategories = [] get categories () { return this.$store.state.category.categoryList } - get sameNameCategories () { - if (!this.categoryName || !this.groupName) { - return [] - } - return this.categories - .filter(x => x.group === this.groupName && x.title === this.categoryName) - } - @Watch('value') onOpen (newVal: boolean) { - this.categoryName = '' - this.groupNameInternal = this.groupName + // wait for vue to render form + this.$nextTick(() => { + this.$refs.form.resetValidation() + this.categoryName = '' + this.groupNameInternal = this.groupName + }) } close () { this.$emit('input', false) } + calcSameNameCategories () { + if (!this.categoryName || !this.groupNameInternal) { + return [] + } + return this.categories + .filter(x => x.group === this.groupNameInternal && x.title === this.categoryName) + } + async submit () { if (!this.$refs.form.validate()) { return } - + this.sameNameCategories = this.calcSameNameCategories() if (this.sameNameCategories.length) { const isDuplicationConfirmed = await this.confirmDuplicate() if (!isDuplicationConfirmed) { diff --git a/front/client/components/AddItemDialog.vue b/front/client/components/AddItemDialog.vue index b17bc1e..3be46b9 100644 --- a/front/client/components/AddItemDialog.vue +++ b/front/client/components/AddItemDialog.vue @@ -28,17 +28,20 @@ autofocus class="mb-2" label="Item name" + data-testid="AddItemDialog-NameInput" :rules="nameValidationRules" v-model="name" /> @@ -57,6 +60,7 @@ diff --git a/front/client/components/Categories.vue b/front/client/components/Categories.vue index 28a76e8..f118099 100644 --- a/front/client/components/Categories.vue +++ b/front/client/components/Categories.vue @@ -2,18 +2,32 @@
+ +
-
-

+
+

{{ groupName }}

+ - - - Add new category - +

@@ -76,6 +83,7 @@ import Vue from 'vue' import Component from 'vue-class-component' import AddCategoryDialog from 'client/components/AddCategoryDialog.vue' +import AddCategoryBtn from 'client/components/AddCategoryBtn.vue' import _groupBy from 'lodash/groupBy' import _sortBy from 'lodash/sortBy' import _fromPairs from 'lodash/fromPairs' @@ -84,7 +92,8 @@ import { ICategoryInfo, CategoryStatus } from 'client/service/Category' @Component({ components: { - AddCategoryDialog + AddCategoryDialog, + AddCategoryBtn } }) export default class Categories extends Vue { diff --git a/front/client/components/CategoryDescription.vue b/front/client/components/CategoryDescription.vue index d4f3c56..4004f8e 100644 --- a/front/client/components/CategoryDescription.vue +++ b/front/client/components/CategoryDescription.vue @@ -6,12 +6,14 @@ v-else v-html="categoryDescription" class="category-description__content" + data-testid="CategoryDescription-Content" />
$vuetify.icons.rss -

{{categoryTitle}}

+

{{categoryTitle}}

- in {{ categoryGroup }} + in + {{ categoryGroup }}
+