...
 
Commits (682)

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -7,17 +7,14 @@
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
],
"assets": ["assets", "favicon.ico"],
"index": "index.php",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"prefix": "m",
"styles": [
"../node_modules/material-design-lite/dist/material.blue_grey-amber.min.css",
"../node_modules/material-design-icons/iconfont/material-icons.css",
......@@ -26,7 +23,6 @@
"scripts": [
"../node_modules/material-design-lite/dist/material.min.js",
"../node_modules/medium-editor/dist/js/medium-editor.min.js",
"shims/fontawesome.js",
"shims/jitsi-api.min.js"
],
"environmentSource": "environments/environment.ts",
......
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
#Error: Attempt to add a non-ASCII file name.
#
#This can cause problems if you want to work with people on other platforms.
#
#To be portable it is advisable to rename the file.
#
#If you know what you are doing you can disable this check using:
#
# git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
#exec git diff-index --check --cached $against --
# Check for "fdescribe"-esque development artifacts accidentally left in.
# https://gist.github.com/DerLobi/d938ac7dc422145f85e6#gistcomment-2824
STATUS=0
for focus in fdescribe fcontext fit fspecify fexample; do
FILES=$(git diff --staged -G"^\s*$focus\(" --name-only | wc -l)
if [ $FILES -gt 0 ]
then
echo "You forgot to remove a $focus in the following files:"
git diff --staged --name-only -G"^\s*$focus\("
echo ""
STATUS=1
fi
done
exit $STATUS
......@@ -31,7 +31,12 @@ tmtags
Thumbs.db
Desktop.ini
node_modules
cypress/screenshots
cypress/videos
# don't ignore travis config
!/.travis.yml
!/.drone.yml
!/.gitlab
!/.githooks
!/.prettierrc
!.gitattributes
image: markharding/minds-front-base
services:
- docker:dind
stages:
- test
- build
- deploy
- prepare
- review
- deploy:staging
- qa
- deploy:canary
- deploy:production
- cleanup
variables:
CYPRESS_INSTALL_BINARY: 0 # Speeds up the install process
npm_config_cache: '$CI_PROJECT_DIR/.npm'
CYPRESS_CACHE_FOLDER: '$CI_PROJECT_DIR/cache/Cypress'
test:
image: circleci/node:8-browsers
stage: test
script:
- npm install # Should be cached...
- npm ci
- npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
build:
lint:
stage: test
script:
- npm i -g prettier
- prettier --check "src/**/*.ts"
- prettier --check "src/**/*.scss"
- prettier --check "src/**/*.html"
############
# QA Stage #
############
qa:e2e:
image: cypress/browsers:chrome67
stage: qa
variables:
CYPRESS_INSTALL_BINARY: 3.4.1
script:
- npm ci
- >
if [ "$CI_BUILD_REF_NAME" == "master" ]; then
export E2E_DOMAIN=https://www.minds.com
export PRODUCTION=true
else
export E2E_DOMAIN=https://$CI_BUILD_REF_SLUG.$KUBE_INGRESS_BASE_DOMAIN
export PRODUCTION=false
fi
- export CYPRESS_baseUrl=$E2E_DOMAIN
- echo "E2E tests for $CI_BUILD_REF_NAME running against $E2E_DOMAIN with user $CYPRESS_username"
- $(npm bin)/cypress run --browser chrome --record --key $CYPRESS_RECORD_ID --config CYPRESS_baseUrl=$E2E_DOMAIN,production=$PRODUCTION
artifacts:
when: always
paths:
- cypress/screenshots
- cypress/videos
cache:
paths:
- .npm
- cache/Cypress
allow_failure: true #manual inspection in case of timeouts
qa:manual:
stage: qa
script:
- echo "Manually approved"
when: manual
only:
refs:
- master
- test/gitlab-ci
allow_failure: false
###############
# Build Stage #
###############
build:review:
stage: build
before_script:
- sed -ri "s|'VERSION'|'$CI_PIPELINE_ID'|" src/environments/environment.prod.ts
script:
- npm install # TODO: Why is this needed?
- npm ci && npm install -g gulp-cli
- npm run postinstall
- gulp build.sass && gulp build.sass ##weird build needs to be run twice for now
- sh build/base-locale.sh dist
artifacts:
name: '$CI_COMMIT_REF_SLUG'
paths:
- dist
except:
refs:
- master
- test/gitlab-ci
build:production:en:
stage: build
before_script:
- sed -ri "s|'VERSION'|'$CI_PIPELINE_ID'|" src/environments/environment.prod.ts
script:
- npm ci && npm install -g gulp-cli
- npm run postinstall
- npm install -g gulp-cli
- gulp build.sass --deploy-url=https://cdn-assets.minds.com/front/dist/en && gulp build.sass --deploy-url=https://cdn-assets.minds.com/front/dist/en ##weird build needs to be run twice for now
- sh build/base-locale.sh dist https://cdn-assets.minds.com/front/dist
- sh build/i18n-locales-all.sh dist https://cdn-assets.minds.com/front/dist
cache:
artifacts:
name: '$CI_COMMIT_REF_SLUG'
paths:
- dist
policy: push
- dist/en
only:
refs:
- master
- test/gitlab-ci
deploy:
stage: deploy
build:production:i18n:
stage: build
before_script:
- sed -ri "s|'VERSION'|'$CI_PIPELINE_ID'|" src/environments/environment.prod.ts
script:
- apk add --no-cache python py-pip
- pip install awscli
- aws s3 sync dist $REPOSITORY_URL
- aws ecs update-service --service=$SERVICE --force-new-deployment --region us-east-1 --cluster=$CLUSTER
cache:
- npm ci && npm install -g gulp-cli
- npm run postinstall
- gulp build.sass --deploy-url=https://cdn-assets.minds.com/front/dist/en && gulp build.sass --deploy-url=https://cdn-assets.minds.com/front/dist/en ##weird build needs to be run twice for now
- sh build/i18n-locales-all.sh dist https://cdn-assets.minds.com/front/dist
artifacts:
name: '$CI_COMMIT_REF_SLUG'
paths:
- dist
policy: pull
- dist/vi
only:
refs:
- master
- test/gitlab-ci
#################
# Prepare Stage #
#################
.sentry_prepare: &sentry_prepare
stage: prepare
image: getsentry/sentry-cli
script:
- echo "Create a new release $CI_PIPELINE_ID"
- sentry-cli releases new $CI_PIPELINE_ID
- sentry-cli releases set-commits --auto $CI_PIPELINE_ID
- sentry-cli releases files $CI_PIPELINE_ID upload-sourcemaps $CI_PROJECT_DIR/dist/en -x .js -x .map --validate --url-prefix $SOURCEMAP_PREFIX
- sentry-cli releases finalize $CI_PIPELINE_ID
- echo "Finalized release for $CI_PIPELINE_ID"
prepare:review:
stage: prepare
image: minds/ci:latest
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
- docker build -t $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID -f containers/front-init/Dockerfile dist/.
- docker push $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID
dependencies:
- build:review
except:
refs:
- master
- test/gitlab-ci
prepare:review:sentry:
<<: *sentry_prepare
variables:
SOURCEMAP_PREFIX: '~/en'
except:
refs:
- master
- test/gitlab-ci
dependencies:
- build:review
prepare:production:
stage: prepare
image: minds/ci:latest
services:
- docker:dind
script:
- docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
- docker build -t $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID -f containers/front-init/Dockerfile dist/.
- docker push $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID
only:
refs:
- master
- test/gitlab-ci
dependencies:
- build:production:en
- build:production:i18n
prepare:production:sentry:
<<: *sentry_prepare
variables:
SOURCEMAP_PREFIX: '~/front/dist/en'
only:
refs:
- master
- test/gitlab-ci
dependencies:
- build:production:en
- build:production:i18n
################
# Review Stage #
################
.cleanup_review: &cleanup_review
image: minds/helm-eks:latest
script:
- aws eks update-kubeconfig --name=sandbox
- helm del --purge $CI_BUILD_REF_SLUG
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_BUILD_REF_SLUG.$KUBE_INGRESS_BASE_DOMAIN
action: stop
variables:
GIT_STRATEGY: none
except:
refs:
- master
- test/gitlab-ci
review:start:
stage: review
image: minds/helm-eks:latest
script:
- aws eks update-kubeconfig --name=sandbox
- git clone --branch=master https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/minds/helm-charts.git
- "helm upgrade \
--install \
--reuse-values \
--set frontInit.image.repository=$CI_REGISTRY_IMAGE/front-init \
--set-string frontInit.image.tag=$CI_PIPELINE_ID \
--set domain=$CI_BUILD_REF_SLUG.$KUBE_INGRESS_BASE_DOMAIN \
--set elasticsearch.clusterName=$CI_BUILD_REF_SLUG--elasticsearch \
--wait \
$CI_BUILD_REF_SLUG \
./helm-charts/minds"
# Update sentry
- sentry-cli releases deploys $CI_PIPELINE_ID new -e review-$CI_COMMIT_REF_SLUG
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_BUILD_REF_SLUG.$KUBE_INGRESS_BASE_DOMAIN
on_stop: review:stop
except:
refs:
- master
- test/gitlab-ci
review:stop:
<<: *cleanup_review
stage: review
when: manual
################
# Deploy Stage #
################
.deploy: &deploy
image: minds/ci:latest
services:
- docker:dind
script:
## Sync assets with CDN
- aws s3 sync dist $S3_REPOSITORY_URL
- $(aws ecr get-login --no-include-email --region us-east-1)
## Update docker front-init container
- docker login -u gitlab-ci-token -p ${CI_BUILD_TOKEN} ${CI_REGISTRY}
- docker pull $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID
- docker tag $CI_REGISTRY_IMAGE/front-init:$CI_PIPELINE_ID $ECR_REPOSITORY_URL:$IMAGE_LABEL
- docker push $ECR_REPOSITORY_URL:$IMAGE_LABEL
## Deploy the new container in rolling restart
- aws ecs update-service --service=$ECS_SERVICE --force-new-deployment --region us-east-1 --cluster=$ECS_CLUSTER
## Update sentry
- sentry-cli releases deploys $CI_PIPELINE_ID new -e $IMAGE_LABEL
dependencies:
- build:production:en
- build:production:i18n
only:
refs:
- master
- test/gitlab-ci
staging:fpm:
<<: *deploy
stage: deploy:staging
variables:
IMAGE_LABEL: 'staging'
ECS_SERVICE: $ECS_APP_STAGING_SERVICE
environment:
name: staging
url: https://www.minds.com # requires staging cookie
deploy:canary:
<<: *deploy
stage: deploy:canary
variables:
IMAGE_LABEL: 'canary'
ECS_SERVICE: $ECS_APP_CANARY_SERVICE
environment:
name: canary
url: https://www.minds.com/?canary=1 # requires canary cookie
when: manual
allow_failure: false # prevents auto deploy to full production
deploy:production:
<<: *deploy
stage: deploy:production
variables:
IMAGE_LABEL: 'production'
ECS_SERVICE: $ECS_APP_PRODUCTION_SERVICE
environment:
name: production
url: https://www.minds.com
when: delayed
start_in: 12 hours # reduce? can always be deployed manually earlier too
#################
# Cleanup stage #
#################
cleanup:review: # We stop the review site after the e2e tests have run
<<: *cleanup_review
stage: cleanup
when: manual
except:
refs:
- master
- test/gitlab-ci
### Summary
(What is the Merge request intending to do, in plain language)
(Be sure to associate any related issues or merge requests)
### Steps to test
(Steps to demonstrate merge achieves goal)
(Include any platform specific directions)
### Estimated Regression Scope
(What features do these changes effect in your estimation?)
# .prettierrc
# Use this file to define your defaults for prettier
# For a list of all available options:
# https://prettier.io/docs/en/options.html
trailingComma: 'es5'
printWidth: 80
singleQuote: true
semi: true
......@@ -6,7 +6,7 @@ Minds Front
Front-end web application for Minds. Please run inside of [the Minds repo](https://github.com/minds/minds).
## Documentation
Documentation for Minds can be found at [minds.org/docs](https://www.minds.org/docs)
Please see the documentation on [developers.minds.com](https://developers.minds.com) for instructions on how to [build the Minds Front-end](https://developers.minds.com/docs/guides/frontend).
### Building
Please see the documentation on Minds.org for instructions on how to [build the Minds Front-end](https://www.minds.org/docs/install/preparation.html#front-end).
......
......@@ -17,19 +17,16 @@
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"extractCss": true,
"assets": [
"src/assets",
"src/favicon.ico"
],
"assets": ["src/assets", "src/favicon.ico"],
"styles": [
"node_modules/material-design-lite/dist/material.blue_grey-amber.min.css",
"node_modules/plyr/dist/plyr.css",
"node_modules/material-design-icons/iconfont/material-icons.css",
"src/main.css"
],
"scripts": [
"node_modules/material-design-lite/dist/material.min.js",
"node_modules/medium-editor/dist/js/medium-editor.min.js",
"src/shims/fontawesome.js",
"src/shims/jitsi-api.min.js"
]
},
......@@ -37,7 +34,11 @@
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"sourceMap": {
"hidden": true,
"scripts": true,
"styles": true
},
"extractCss": true,
"namedChunks": false,
"aot": true,
......@@ -50,6 +51,14 @@
"with": "src/environments/environment.prod.ts"
}
]
},
"hmr": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.hmr.ts"
}
]
}
}
},
......@@ -61,6 +70,10 @@
"configurations": {
"production": {
"browserTarget": "v5.x:build:production"
},
"hmr": {
"hmr": true,
"browserTarget": "v5.x:build:hmr"
}
}
},
......@@ -79,25 +92,16 @@
"scripts": [
"node_modules/material-design-lite/dist/material.min.js",
"node_modules/medium-editor/dist/js/medium-editor.min.js",
"src/shims/fontawesome.js",
"src/shims/jitsi-api.min.js"
],
"assets": [
"src/assets",
"src/favicon.ico"
]
"assets": ["src/assets", "src/favicon.ico"]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
"tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"],
"exclude": ["**/node_modules/**"]
}
},
"server": {
......@@ -133,12 +137,8 @@
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**"
]
"tsConfig": ["e2e/tsconfig.e2e.json"],
"exclude": ["**/node_modules/**"]
}
}
}
......@@ -147,11 +147,11 @@
"defaultProject": "v5.x",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"prefix": "m",
"styleext": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
"prefix": "m"
}
}
}
#!/bin/sh
ng build --prod --vendor-chunk --output-path="$1/en/" --deploy-url="$2/en/" --build-optimizer=false --source-map=false
export NODE_OPTIONS="--max-old-space-size=3584"
ng build --prod --vendor-chunk --output-path="$1/en/" --deploy-url="$2/en/" --build-optimizer=false
#!/bin/sh
export NODE_OPTIONS="--max-old-space-size=3584"
do_locale_build () {
ng build --prod --vendor-chunk --output-path="$2/$1/" --deploy-url="$3/$1/" --build-optimizer=false --source-map=false \
......
FROM alpine:edge
COPY . dist
## Hack to make initial laguage load
COPY en/index.php dist/index.php
\ No newline at end of file
{}
{
"projectId": "qrjqcv",
"requestTimeout": 3600000,
"responseTimeout": 3600000,
"pageLoadTimeout": 3600000
}
#!/usr/bin/env bash
# Boilerplate generated with create-bash-script (c) 2019 Nikita Skobov
# Available https://github.com/nikita-skobov/create-bash-script
function usage()
{
local just_help=$1
local missing_required=$2
local invalid_argument=$3
local invalid_option=$4
local help="Usage: e2e.sh [OPTIONS]
Intended to serve as an interaction wrapper around Cypress. Ensure that you run from within the project.
Example: ./e2e.sh -u nemofin -p password123 -v true -h http://www.minds.com/
Options (* indicates it is required):"
local help_options="
*\-p ,\--password \<Parameter>\ The password of the user.
\-h ,\--url \<Parameter>\ The URL of the host e.g. https://www.minds.com/ - defaults to use localhost.
\-u ,\--username \<Parameter>\ The username - defaults to cypress_e2e_test.
\-pu ,\--pro_username \<Parameter>\ The pro users username.
\-pp ,\--pro_password \<Parameter>\ The pro users password
\-v ,\---video \<Parameter>\ true if you want video providing.
\-e, \--env \<Parameter>\ add additional env variables e.g. production=true
"
if [ "$missing_required" != "" ]
then
echo "Missing required argument: $missing_required"
fi
if [ "$invalid_option" != "" ] && [ "$invalid_value" = "" ]
then
echo "Invalid option: $invalid_option"
elif [ "$invalid_value" != "" ]
then
echo "Invalid value: $invalid_value for option: --$invalid_option"
fi
echo -e "
"
echo "$help"
echo "$help_options" | column -t -s'\'
return
}
function init_args()
{
REQ_ARGS=( "password" )
# get command line arguments
POSITIONAL=()
# set default arguments
url="http://localhost"
username="minds_cypress_tests"
pro_username="minds_pro_cypress_tests"
pro_password=""
env=""
_video=false
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-h|--url)
url="$2"
shift 2
;;
-u|--username)
username="$2"
shift 2
;;
-p|--password)
password="$2"
shift 2
;;
-v|--video)
_video="$2"
shift 2
;;
-pu|--pro-username)
pro_username="$2"
shift 2
;;
-pp|--pro-password)
pro_password="$2"
shift 2
;;
-e|--env)
env=",$2"
shift 2
;;
*)
POSITIONAL+=("$1") # saves unknown option in array
shift
;;
esac
done
for i in "${REQ_ARGS[@]}"; do
# $i is the string of the variable name
# ${!i} is a parameter expression to get the value
# of the variable whose name is i.
req_var=${!i}
if [ "$req_var" = "" ]
then
usage "" "--$i"
exit
fi
done
}
init_args $@
# cd to project root.
while [[ $PWD != '/' && ${PWD##*/} != 'front' ]]; do cd ..; done
#run cypress with args.
echo $(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password,pro_username=$pro_username,pro_password=$pro_password$env $POSITIONAL
$(npm bin)/cypress open --config baseUrl=$url,video=$_video --env username=$username,password=$password,pro_username=$pro_username,pro_password=$pro_password$env $POSITIONAL
cypress/fixtures/avatar.jpeg

8.1 KB

context('Rewards Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const joinRewards = '.m-marketing__mainWrapper .mf-button';
it('should have a join rewards button', () => {
cy.visit('/rewards');
cy.get(joinRewards)
.should('be.visible')
.should('contain', 'Join Rewards')
.click();
cy.location('pathname').should(
'contains',
'/wallet/tokens/contributions'
);
});
});
context('Token Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
cy.visit('/token');
});
it('should have the ability to trigger Buy Tokens modal', () => {
const tokensInput = 'm-blockchain--purchase input[name=amount]';
const buyTokensButton =
'm-blockchain--purchase .m-blockchainTokenPurchase__action .mf-button';
const anyBuyTokensModal =
'm-blockchain--purchase m-modal .m-modal-container';
cy.get(tokensInput)
.focus()
.clear()
.type('0');
cy.get(buyTokensButton).should('be.disabled');
cy.get(tokensInput)
.focus()
.clear()
.type('1');
cy.get(buyTokensButton)
.should('not.be.disabled')
.click();
cy.get('.m-get-metamask--cancel-btn.m-btn').click();
cy.get(anyBuyTokensModal).should('be.visible');
});
it('should have the ability to trigger Buy Eth modal', () => {
const buyEthLink =
'm-blockchain--purchase .m-blockchainTokenPurchase__ethRate a';
const buyEthModal = 'm-blockchain__eth-modal .m-modal-container';
cy.get(buyEthLink).click();
cy.get(buyEthModal).should('be.visible');
});
});
This diff is collapsed.
/**
* @author Ben Hayward
* @desc E2E testing for Minds Boost Console pages.
*/
import generateRandomId from '../../support/utilities';
context('Boost Console', () => {
const postContent = "Test boost, please reject..." + generateRandomId();
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
newBoost(postContent, 500);
});
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route("POST", '**/api/v2/boost/**').as('boostPost');
cy.visit('/boost/console/newsfeed/history');
});
it('should show a new boost in the console', () => {
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.should('not.contain', 'revoked');
cy.get('m-boost-console-card:nth-child(1) .m-mature-message span')
.contains(postContent);
});
it('should allow a revoke a boost', () => {
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.should('not.contain', 'revoked');
cy.get('m-boost-console-card:nth-child(1) .m-boost-card--manager-item--buttons > button')
.click();
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.contains('revoked');
});
it('should load show the user content for newsfeed boosts', () => {
cy.route("GET", "**/feeds/container/*/activities**").as("activities");
cy.contains('Create a Boost')
.click()
.location('pathname')
.should('eq', `/boost/console/newsfeed/create`)
.wait('@activities').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
it('should load show the user content for sidebar boosts', () => {
cy.route("GET", "**/api/v2/feeds/container/*/all**").as("all");
cy.visit('/boost/console/content/create')
.location('pathname')
.should('eq', `/boost/console/content/create`)
.wait('@all').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
it('should load show the user content for offers', () => {
cy.route("GET", "**/api/v2/feeds/container/*/activities**").as("all");
cy.visit('/boost/console/offers/create')
.location('pathname')
.should('eq', `/boost/console/offers/create`)
.wait('@all').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
function newBoost(text, views) {
cy.server();
cy.route("POST", '**/api/v2/boost/**').as('boostPost');
cy.visit('/newsfeed/subscribed');
cy.post(text);
cy.get('#boost-actions')
.first()
.click();
cy.get('.m-boost--creator-section-amount input')
.type(views);
cy.get('m-overlay-modal > div.m-overlay-modal > m-boost--creator button')
.click();
cy.wait('@boostPost').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
cy.get('.m-overlay-modal')
.should('not.be.visible')
}
})
/**
* @author Ben Hayward
* @desc E2E testing for Minds Boost Console pages.
*/
import generateRandomId from '../../support/utilities';
context('Boost Console', () => {
const postContent = "Test boost, please reject..." + generateRandomId();
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
newBoost(postContent, 500);
});
beforeEach(() => {
cy.server();
cy.route("POST", '**/api/v2/boost/**').as('boostPost');
cy.preserveCookies();
cy.visit('/boost/console/newsfeed/history');
});
after(() => {
cy.clearCookies();
});
it('should show a new boost in the console', () => {
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.should('not.contain', 'revoked');
cy.get('m-boost-console-card:nth-child(1) .m-mature-message span')
.contains(postContent);
});
it('should allow a revoke a boost', () => {
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.should('not.contain', 'revoked');
cy.get('m-boost-console-card:nth-child(1) .m-boost-card--manager-item--buttons > button')
.click();
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.contains('revoked');
});
it('should load show the user content for newsfeed boosts', () => {
cy.route("GET", "**/feeds/container/*/activities**").as("activities");
cy.contains('Create a Boost')
.click()
.location('pathname')
.should('eq', `/boost/console/newsfeed/create`)
.wait('@activities').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
it('should load show the user content for sidebar boosts', () => {
cy.route("GET", "**/api/v2/feeds/container/*/all**").as("all");
cy.visit('/boost/console/content/create')
.location('pathname')
.should('eq', `/boost/console/content/create`)
.wait('@all').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
it('should load show the user content for offers', () => {
cy.route("GET", "**/api/v2/feeds/container/*/activities**").as("all");
cy.visit('/boost/console/offers/create')
.location('pathname')
.should('eq', `/boost/console/offers/create`)
.wait('@all').then((xhr) => {
expect(xhr.status).to.equal(200);
});
})
function newBoost(text, views) {
cy.server();
cy.route("POST", '**/api/v2/boost/**').as('boostPost');
cy.visit('/newsfeed/subscribed');
cy.post(text);
cy.get('#boost-actions')
.first()
.click();
cy.get('.m-boost--creator-section-amount input')
.type(views);
cy.get('m-overlay-modal > div.m-overlay-modal > m-boost--creator button')
.click();
cy.wait('@boostPost').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
cy.get('.m-overlay-modal')
.should('not.be.visible')
}
})
// Cannot test until env behaves consistently else,
// the test will frequently error when it cant see a boost.
context.skip('Boost Impressions', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
});
beforeEach(()=> {
cy.server();
cy.route("POST", "**api/v2/analytics/views/boost/*").as("analytics");
cy.route("GET", "**/api/v2/feeds/subscribed/activities**").as("activities");
cy.preserveCookies();
cy.visit('/newsfeed/subscriptions')
.location('pathname')
.should('eq', `/newsfeed/subscriptions`)
.wait('@activities').then((xhr) => {
expect(xhr.status).to.equal(200);
});
});
afterEach(()=> {
cy.reload();
})
it('should register views on scroll', () => {
//smooth scroll
cy.scrollTo('0', '1%', { duration: 100 });
//assert
cy.wait('@analytics').then((xhr) => {
expect(xhr.status).to.equal(200);
});
});
it('should register views on boost rotate', () => {
//rotate forward and wait to trigger analytics
cy.get('m-newsfeed--boost-rotator')
.find('chevron_right')
.click();
//assert
cy.wait('@analytics').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
//rotate forward and wait to trigger analytics
cy.get('m-newsfeed--boost-rotator')
.find('chevron_left')
.click();
//assert
cy.wait('@analytics').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
});
});
context('Boost Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const createBoostButton = '.m-marketing__mainWrapper .mf-button';
it('should have a create boost button', () => {
cy.visit('/boost');
cy.get(createBoostButton)
.should('be.visible')
.should('contain', 'Create Boost')
.click();
cy.location('pathname').should(
'contains',
'/boost/console/newsfeed/create'
);
});
});
/**
* Skipping until sandbox behaves consistently as currently when posting,
* on the sandboxes it does not show your latest image after you have posted it.
* The below code should be functioning correctly once this is resolved.
*/
context.skip('Channel image upload', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit('/newsfeed/subscriptions')
.location('pathname')
.should('eq', '/newsfeed/subscriptions');
});
beforeEach(()=> {
cy.preserveCookies();
cy.server();
cy.route("POST", "**/api/v1/newsfeed").as("newsfeedPOST");
cy.route("POST", "**/api/v1/media").as("mediaPOST");
});
it('should post an activity with an image attachment', () => {
cy.get('minds-newsfeed-poster').should('be.visible');
cy.get('minds-newsfeed-poster textarea').type('This is a post with an image');
cy.uploadFile('#attachment-input-poster', '../fixtures/international-space-station-1776401_1920.jpg', 'image/jpg');
//upload image
cy.wait('@mediaPOST');
cy.get('.m-posterActionBar__PostButton').click();
//await response for activity
cy.wait('@newsfeedPOST').then((xhr) => {
expect(xhr.status).to.equal(200);
const uploadedImageGuid = xhr.response.body.activity.entity_guid
const activityGuid = xhr.response.body.guid;
cy.get('.minds-list > minds-activity:first-child .message').contains('This is a post with an image');
// assert image
cy.get('.minds-list > minds-activity:first-child .item-image img').should('be.visible');
cy.visit(`/${Cypress.env().username}`);
let mediaHref = `/media/${uploadedImageGuid}`;
cy.get("m-channels--sorted-module[title='Images']")
.find(`a[href='${mediaHref}']`);
cy.get(`[data-minds-activity-guid='${activityGuid}']`)
.find('m-post-menu .minds-more')
.click();
cy.get(`[data-minds-activity-guid='${activityGuid}']`)
.find("li:contains('Delete')")
.click();
cy.get(`[data-minds-activity-guid='${activityGuid}'] m-post-menu m-modal-confirm .mdl-button--colored`).click();
});
});
});
// skipped until feat release
context.skip('Channel', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit(`/${Cypress.env().username}`);
});
beforeEach(()=> {
cy.preserveCookies();
});
after(()=> {
cy.get('.m-channel-mode-selector--dropdown')
.click()
.find(".m-dropdown--list--item:contains('Public')")
.should('be.visible')
.click();
});
it('should change channel mode to public', () => {
cy.get('.m-channel-mode-selector--dropdown')
.click()
.find(".m-dropdown--list--item:contains('Public')")
.should('be.visible')
.click();
cy.get('.m-channel-mode-selector--dropdown')
.find('label').contains('Public');
});
it('should change channel mode to moderated', () => {
cy.get('.m-channel-mode-selector--dropdown')
.click()
.find(".m-dropdown--list--item:contains('Moderated')")
.should('be.visible')
.click();
cy.get('.m-channel-mode-selector--dropdown')
.find('label').contains('Moderated');
});
it('should change channel mode to closed', () => {
cy.get('.m-channel-mode-selector--dropdown')
.click()
.find(".m-dropdown--list--item:contains('Closed')")
.should('be.visible')
.click();
cy.get('.m-channel-mode-selector--dropdown')
.find('label').contains('Closed');
});
});
// skipped until feat release
context.skip('Comment Permissions', () => {
const postMenu = 'minds-activity:first > div > m-post-menu';
const deletePostOption = "m-post-menu > ul > li:visible:contains('Delete')";
const deletePostButton = ".m-modal-confirm-buttons > button:contains('Delete')";
before(() => {
//make a post new.
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit('/newsfeed/subscriptions');
cy.location('pathname')
.should('eq', `/newsfeed/subscriptions`);
});
afterEach(() => {
//delete the post
cy.get(postMenu).click();
cy.get(deletePostOption).click();
cy.get(deletePostButton).click();
});
beforeEach(()=> {
cy.preserveCookies();
cy.post('test post');
});
it('should disable comments', () => {
cy.server();
cy.route("POST", "**/api/v2/permissions/comments/**").as("commentToggle");
cy.get(postMenu)
.click()
.find("li:visible:contains('Disable Comments')")
.click();
cy.wait('@commentToggle').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
expect(xhr.response.body.allowed).to.equal(false);
});
//close menu
cy.get(postMenu)
.click();
cy.get('minds-activity:first')
.find("i:contains('speaker_notes_off')")
.click();
});
it('should allow comments', () => {
cy.server();
cy.route("POST", "**/api/v2/permissions/comments/**").as("commentToggle");
cy.get(postMenu)
.click()
.find("li:visible:contains('Disable Comments')")
.click();
cy.wait('@commentToggle').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
expect(xhr.response.body.allowed).to.equal(false);
});
//Menu stays open
cy.get("li:visible:contains('Allow Comments')")
.click();
cy.wait('@commentToggle').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
expect(xhr.response.body.allowed).to.equal(true);
});
//close menu
cy.get(postMenu)
.click();
cy.get('minds-activity:first')
.find("i:contains('chat_bubble')");
});
});
/**
* @author Ben Hayward
* @create date 2019-08-09 14:42:51
* @modify date 2019-08-09 14:42:51
* @desc Spec tests for comment threads.
*/
context('Comment Threads', () => {
const testMessage = {
1: 'test tier 1',
2: 'test tier 2',
3: 'test tier 3',
};
const postMenu = 'minds-activity:first > div > m-post-menu > button > i';
const deletePostOption = "m-post-menu > ul > li:visible:contains('Delete')";
const deletePostButton = ".m-modal-confirm-buttons > button:contains('Delete')";
const postCommentButton = 'm-comment__poster > div > div.minds-body > div > div > a.m-post-button';
const thumbsUpCounters = '.m-comment__toolbar > div > minds-button-thumbs-up > a > span';
const thumbsDownCounters = '.m-comment__toolbar > div > minds-button-thumbs-down > a > span';
// pass in tier / tree depth.
const replyButton = `minds-activity:first .m-comment__toolbar > div > span`;
const commentButton = `minds-activity:first minds-button-comment`;
const commentInput = `minds-activity:first m-text-input--autocomplete-container > minds-textarea > div`;
const commentContent = `minds-activity:first m-comments__tree .m-comment__bubble > p`;
before(() => {
//make a post new.
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit('/newsfeed/subscriptions');
cy.location('pathname')
.should('eq', `/newsfeed/subscriptions`);
cy.post('test post');
});
beforeEach(()=> {
cy.preserveCookies();
});
after(() => {
//delete the post
cy.get(postMenu).click();
cy.get(deletePostOption).click();
cy.get(deletePostButton).click();
});
it('should post three tiers of comments', () => {
//Reveal the conversation
cy.get(commentButton).click();
//Add the first level of comments
cy.get(commentInput).type(testMessage[1]);
cy.get(postCommentButton).click();
cy.get(commentContent).contains(testMessage[1]);
//Add the second level of comments
cy.get(replyButton).click();
cy.get(commentInput)
.first()
.type(testMessage[2]);
cy.get(postCommentButton)
.first()
.click();
cy.get(commentContent).contains(testMessage[2]);
//Add the third level of comments
cy.get('minds-activity:first')
.find('m-comments__tree m-comments__thread m-comment')
.find('m-comments__thread m-comment:nth-child(2) .m-comment__toolbar > div > span')
.last()
.click();
cy.get(commentInput)
.first()
.type(testMessage[3]);
cy.get(postCommentButton)
.first()
.click();
cy.get(commentContent).contains(testMessage[3]);
//click thumbs up and down
cy.get('.m-comment__toolbar')
.find('minds-button-thumbs-up')
.click({multiple: true});
cy.get('.m-comment__toolbar')
.find('minds-button-thumbs-down')
.click({multiple: true});
// check the values
cy.get(thumbsUpCounters)
.each((counter) => expect(counter.context.innerHTML).to.eql('1'));
cy.get(thumbsDownCounters)
.each((counter) => expect(counter.context.innerHTML).to.eql('1'));
});
})
context('Discovery', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit('/newsfeed/global/top')
.location('pathname')
.should('eq', '/newsfeed/global/top');
});
beforeEach(()=> {
cy.preserveCookies();
});
it('should allow a user to post on the discovery page', () => {
cy.post("test!!");
});
it('should be able to filter by hot', () => {
cy.get(".m-sort-selector--algorithm-dropdown ul > li:contains('Hot')")
.click()
.should('have.class', 'm-dropdown--list--item--selected'); // selected class
cy.url().should('include', '/hot');
});
it('should be able to filter by top', () => {
cy.get(".m-sort-selector--algorithm-dropdown ul > li:contains('Top')")
.click()
.should('have.class', 'm-dropdown--list--item--selected'); // selected class
cy.url().should('include', '/top');
});
it('should be able to filter by time in the top feed', () => {
cy.get('.m-sort-selector--period-dropdown').click();
cy.get(".m-sort-selector--period-dropdown ul > li:contains('30d')").click();
cy.url().should('include', '=30d');
cy.get('.m-sort-selector--period-dropdown').click();
cy.get(".m-sort-selector--period-dropdown ul > li:contains('7d')").click();
cy.url().should('include', '=7d');
cy.get('.m-sort-selector--period-dropdown').click();
cy.get(".m-sort-selector--period-dropdown ul > li:contains('24h')").click();
cy.url().should('include', '=24h');
cy.get('.m-sort-selector--period-dropdown').click();
cy.get(".m-sort-selector--period-dropdown ul > li:contains('12h')").click();
cy.url().should('include', '=12h');
});
it('should filter by latest', () => {
cy.get(".m-sort-selector--algorithm-dropdown ul > li:contains('Latest')")
.click()
.should('have.class', 'm-dropdown--list--item--selected'); // selected class
cy.url().should('include', '/latest');
});
it('should filter by image', () => {
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('photo')")
.click();
cy.url().should('include', '=images');
});
it('should filter by video', () => {
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('videocam')")
.click();
cy.url().should('include', '=videos');
});
it('should filter by blog', () => {
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('subject')")
.click();
cy.url().should('include', '=blog');
});
it('should filter by channels', () => {
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('people')")
.click();
cy.url().should('include', '=channels');
});
it('should filter by groups', () => {
cy.visit('/newsfeed/global/hot');
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('group_work')")
.click();
cy.url().should('include', '=groups');
});
it('should filter by all', () => {
cy.visit('/newsfeed/global/top?type=images');
cy.get('.m-sort-selector--custom-type-dropdown').click();
cy.get(".m-sort-selector--custom-type-dropdown ul > li:contains('all_inclusive')")
.click();
cy.url().should('not.include', '=images');
});
it('should allow the user to toggle nsfw', () => {
cy.visit('/newsfeed/global/top?type=images');
cy.get('m-topbar--navigation--options').click();
cy.get('m-topbar--navigation--options label > span').click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Nudity')").click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Pornography')").click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Profanity')").click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Violence and Gore')").click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Race and Religion')").click();
cy.get("m-topbar--navigation--options ul > m-nsfw-selector ul > li:contains('Other')").click();
});
it('should allow the user to turn off single hashtag filter and view all posts', () => {
cy.visit('/newsfeed/global/top');
cy.get('m-hashtagssidebarselector__item')
.first()
.click();
});
it.skip('should allow the user to toggle a single hashtag and then toggle back to the initial feed', () => {
cy.visit('/newsfeed/global/top');
// get first label value
cy.get('.m-hashtagsSidebarSelectorList__label').first().invoke('text').then((text) => {
// repeat twice to capture full cycle.
Cypress._.times(2, (i) => {
// split hashtag off of label text
let label = text.split('#')[1];
// click switch
toggleFirstVisibilitySwitch();
// check location name has updated
cy.location('pathname')
.should('eq', `/newsfeed/global/top;period=12h;hashtag=${label}`);
// click switch
toggleFirstVisibilitySwitch();
// check location name has updated
cy.location('pathname')
.should('eq', `/newsfeed/global/top;period=12h`);
});
});
});
// click first visibility switch
const toggleFirstVisibilitySwitch = () => {
cy.get('m-hashtagssidebarselector__item')
.first()
.find('.m-hashtagsSidebarSelectorList__visibility > i')
.click();
}
})
context('Groups', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
});
beforeEach(()=> {
cy.preserveCookies();
});
it('should create and edit a group', () => {
cy.server();
cy.route("POST", "**/api/v1/groups/group*").as("postGroup");
cy.get('m-group--sidebar-markers li:first-child').contains('New group').click();
cy.location('pathname').should('eq', '/groups/create');
// add a banner
cy.uploadFile('minds-banner #file', '../fixtures/international-space-station-1776401_1920.jpg', 'image/jpg');
// add a name
cy.get('.m-group-info-name > input').type('test');
// add a description
cy.get('.m-group-info-brief-description > textarea').type('This is a test');
// click on hashtags dropdown
cy.get('m-hashtags-selector .m-dropdown--label-container').click();
// select #ART
cy.get('m-hashtags-selector m-dropdown m-form-tags-input > div > span').contains('art').click();
// type in another hashtag manually
cy.get('m-hashtags-selector m-form-tags-input input').type('hashtag{enter}').click();
// click away
cy.get('m-hashtags-selector .minds-bg-overlay').click();
cy.get('.m-groups-save > button').contains('Create').click();
cy.route("POST", "**/api/v1/groups/group/*/banner*").as("postBanner");
cy.wait('@postGroup').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
}).wait('@postBanner').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
});
cy.get('.m-groupInfo__name').contains('test');
cy.get('.m-groupInfo__description').contains('This is a test');
// open settings button
cy.get('minds-groups-settings-button > button').click();
cy.get('minds-groups-settings-button ul.minds-dropdown-menu li:first-child').contains('Edit').click();
// edit name
cy.get('.m-groupInfo__name input').type(' group');
// edit description
cy.get('.m-groupInfo__description textarea').type(' group');
// open settings button
cy.get('minds-groups-settings-button > button').click();
cy.get('minds-groups-settings-button ul.minds-dropdown-menu li:first-child').contains('Save').click();
cy.get('.m-groupInfo__name').contains('test group');
cy.get('.m-groupInfo__description').contains('This is a test group');
})
it('should be able to toggle conversation and comment on it', () => {
cy.get("m-group--sidebar-markers li:contains('test group')")
.first()
.click();
// toggle the conversation
cy.get('.m-groupGrid__right').should('be.visible');
cy.get('.m-groupGrid__toggleBtn').click();
cy.get('.m-groupGrid__right').should('not.be.visible');
cy.get('.m-groupGrid__toggleBtn').click();
// comment
cy.get('minds-groups-profile-conversation m-comments__tree minds-textarea .m-editor').type('lvl 1 comment');
cy.get('minds-groups-profile-conversation m-comments__tree a.m-post-button').click();
// comment should appear on the list
cy.get('minds-groups-profile-conversation m-comments__tree > m-comments__thread .m-commentBubble__message').contains('lvl 1 comment');
cy.on('window:confirm', (str) => {
return true;
});
})
it('should post an activity inside the group and record the view when scrolling', () => {
cy.get("m-group--sidebar-markers li:contains('test group')")
.first()
.click();
cy.server();
cy.route("POST", "**/api/v2/analytics/views/activity/*").as("view");
cy.get('minds-newsfeed-poster textarea').type('This is a post');
cy.get('.m-posterActionBar__PostButton').click();
// the activity should show that it was posted in this group
cy.get('.minds-list minds-activity .body a:nth-child(2)').contains('(test group)');
cy.get('.minds-list minds-activity .m-mature-message-content').contains('This is a post');
// create the post
cy.get('minds-newsfeed-poster textarea').type('This is a post that will record a view');
cy.get('.m-posterActionBar__PostButton').click();
cy.scrollTo(0, '20px');
cy.wait('@view').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body).to.deep.equal({ status: 'success' });
});
});
it('should delete a group', () => {
cy.get('m-group--sidebar-markers li:nth-child(3)').contains('test group').click();
// cleanup
cy.get('minds-groups-settings-button > button').click();
cy.get('minds-groups-settings-button ul.minds-dropdown-menu > li:nth-child(8)').contains('Delete Group').click();
cy.get('minds-groups-settings-button m-modal .mdl-button--raised').contains('Confirm').click();
cy.location('pathname').should('eq', '/groups/member');
})
})
context('Login', () => {
beforeEach(() => {
cy.clearCookies();
cy.visit('/')
})
it('should login', () => {
cy.get('.m-btn--login').click();
cy.get('.m-v2-topbar__Container__LoginWrapper > a').click();
cy.location('pathname').should('eq', '/login');
......@@ -17,11 +18,12 @@ context('Login', () => {
cy.get('minds-form-login .m-btn--login').click();
cy.location('pathname').should('eq', '/newsfeed/subscriptions');
cy.location('pathname')
.should('eq', '/newsfeed/subscriptions');
})
it('should fail to login because of incorrect password', () => {
cy.get('.m-btn--login').click();
cy.get('.m-v2-topbar__Container__LoginWrapper > a').click();
cy.location('pathname').should('eq', '/login');
......
/**
* @author Ben Hayward
* @desc Spec tests for comment threads.
*/
import generateRandomId from '../support/utilities';
context('Messenger', () => {
const targetUser = 'minds';
const messagePassword = 'Passw0rd!';
const messageContent = 'this is a test message!';
const undecryptedMessage = ''
const testUsername = generateRandomId();
const testPassword = generateRandomId()+'X#';
const openMessenger = '.m-messenger--dockpane-tab';
const userSearch = '.m-messenger--userlist-search > input[type=text]';
const userList = (i) => `.m-messenger--userlist-conversations > div:nth-child(${i}) > span.m-conversation-label`;
const passwordInput = (i) => `input[type=password]:nth-child(${i})`;
const submitPassword = 'm-messenger--encryption > div > button';
const messageInput = '.m-messenger--conversation-composer > textarea';
const sendButton = '[data-cy=data-minds-conversation-send]';
const messageBubble = '.m-messenger--conversation-message-bubble';
const settingsButton = '[data-cy=data-minds-conversation-options]';
const closeButton = '[data-cy=data-minds-conversation-close]';
const destroyButton = '[data-cy=data-minds-conversation-destroy]';
before(() => {
cy.newUser(testUsername, testPassword);
});
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route('GET', '**/api/v2/messenger/search?*').as('search');
cy.route('GET', '**/api/v2/messenger/conversations/**').as('conversations');
cy.route('POST', '**/api/v2/messenger/conversations/**').as('send');
cy.route('POST', '**/api/v2/messenger/keys/setup**').as('keys')
cy.get(openMessenger)
.click();
});
afterEach(() => {
cy.get(closeButton)
.click({multiple: true});
cy.get(openMessenger)
.click({multiple: true});
});
after(() => {
cy.deleteUser(testUsername, testPassword);
cy.clearCookies({log: true})
});
it('should allow a new user to set a password and send a message', () => {
cy.get(userSearch)
.type(Cypress.env().username)
.wait('@search').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
cy.get(userList(1))
.click();
cy.get(passwordInput(3))
.type(messagePassword)
cy.get(passwordInput(4))
.type(messagePassword)
cy.get(submitPassword)
.click();
cy.get(messageInput)
.type(messageContent);
cy.get(sendButton)
.click()
.wait('@send').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
});
it('should allow a user to destroy their chat content', () => {
cy.get(userSearch)
.clear()
.type(Cypress.env().username)
.wait('@search').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
cy.get(userList(1))
.click();
cy.get(passwordInput(3))
.type(messagePassword)
cy.get(passwordInput(4))
.type(messagePassword)
cy.get(submitPassword)
.click()
.wait('@keys').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
})
.wait('@conversations').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
cy.get(settingsButton)
.click();
cy.get(destroyButton)
.first()
.click();
cy.get(messageBubble)
.should('not.exist');
});
});
This diff is collapsed.
context('Pro Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const contactUsButton = '.m-marketing__mainWrapper .mf-button';
it('should have a contact us button', () => {
cy.visit('/nodes', {
onBeforeLoad(_window) {
cy.stub(_window, 'open');
},
});
cy.get(contactUsButton)
.should('be.visible')
.should('contain', 'Contact us for details')
.click();
cy.window()
.its('open')
.should('be.called');
});
});
/**
* @author Ben Hayward
* @desc Spec tests for comment threads.
*/
import generateRandomId from '../support/utilities';
context.skip('Notification', () => {
//secondary user for testing.
const username = generateRandomId();
const password = generateRandomId()+'X#';
const commentText = generateRandomId();
const postText = generateRandomId();
const postCommentButton = 'm-comment__poster > div > div.minds-body > div > div > a.m-post-button';
const commentButton = 'minds-activity > div.tabs > minds-button-comment > a';
const commentInput = 'm-comment__poster minds-textarea > div';
const commentContent ='.m-comment__bubble > p';
const notificationBell = 'm-notifications--topbar-toggle > a > i';
const notification = 'minds-notification';
/**
* Before all, generate username and password, login as the new user and log out.
* Next login to env user, make a post, and log out.
*/
before(() => {
cy.newUser(username, password);
cy.logout();
cy.login();
cy.post(postText);
cy.clearCookies();
});
/**
* After all log into new user and delete user.
*/
after(() => {
cy.clearCookies();
cy.login(true, username, password);
cy.visit(`/${Cypress.env().username}`);
cy.deleteUser(username, password);
});
/**
* Before each test login, and visit env users channel.
* When testing, this means you will be ready to make a comment, remind etc,
* then switch users and check for the notification.
*/
beforeEach(() => {
cy.route("GET", '**/api/v1/notifications/all**').as('notifications');
cy.clearCookies();
cy.login(false, username, password);
cy.location('pathname')
.should('eq', '/newsfeed/subscriptions');
cy.visit(`/${Cypress.env().username}`);
});
it('should alert the user that a post has been commented on', () => {
// Comment on generated 2nd users post.
cy.get(commentButton).first().click();
cy.get(commentInput).first().type(commentText);
cy.get(postCommentButton).first().click();
cy.get(commentContent).first().contains(commentText);
// Logout, log into generated user.
cy.logout();
cy.login();
// Open their notifications
cy.get(notificationBell).click()
.wait('@notifications').then((xhr) => {
expect(xhr.status).to.equal(200);
});
cy.get(notification)
.first()
.click();
cy.contains(commentText);
});
})
context('Onboarding', () => {
const email = 'test@minds.com';
const password = 'Passw0rd!';
const name = "Tester";
const description = "I am a tester, with a not so lengthy description";
const welcomeText = "Welcome to Minds!";
const usernameField = 'minds-form-register #username';
const emailField = 'minds-form-register #email';
const passwordField = 'minds-form-register #password';
const password2Field = 'minds-form-register #password2';
const nameField = '#display-name';
const descriptionfield = '#description';
const phoneNumberInput = '#phone';
const countryDropdown = 'm-phone-input--country > div';
const ukOption = 'm-phone-input--country > ul > li:nth-child(2)';
const dialcode = '.m-phone-input--dial-code';
const checkbox = 'minds-form-register label:nth-child(2) .mdl-ripple--center';
const submitButton = 'minds-form-register .mdl-card__actions button';
const nextButton = '.m-channelOnboarding__next';
const submitPhoneButton = 'm-channel--onboarding--rewards > div > div > button';
const loadingSpinner = '.mdl-spinner__gap-patch';
const getTopic = (i) => `m-onboarding--topics > div > ul > li:nth-child(${i}) span`;
before(() => {
cy.clearCookies();
cy.visit('/login');
//type values
cy.get(usernameField).focus().type(Math.random().toString(36).replace('0.', ''));
cy.get(emailField).focus().type(email);
cy.get(passwordField).focus().type(password);
cy.get(password2Field).focus().type(password);
cy.get(checkbox).click();
//submit
cy.get(submitButton).click();
//onboarding modal shown
cy.get('m-onboarding--topics > div > h2:nth-child(1)')
.contains(welcomeText);
});
it('should allow a user to run through onboarding modals', () => {
//select topics
cy.get(getTopic(3)).click().should('have.class', 'selected')
cy.get(getTopic(4)).click().should('have.class', 'selected')
cy.get(getTopic(5)).click().should('have.class', 'selected')
//click
cy.get(nextButton).click();
//TODO: Skipped over for now as subscribed channels is not working on staging environment.
cy.get(nextButton).click();
cy.get(nameField).clear().type(name);
cy.get(descriptionfield).type(description);
cy.get(nextButton).click();
//set dialcode
cy.get(countryDropdown).click();
cy.get(ukOption).click();
cy.get(dialcode).contains('+44');
//type number
cy.get(phoneNumberInput).type('7700000000');
//submit and check loading spinner.
cy.get(submitPhoneButton).click();
cy.get(loadingSpinner).should('be.visible');
cy.get(nextButton).click();
});
});
context('Plus Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const upgradeButton = 'm-plus--subscription .mf-button';
const wirePaymentsComponent = 'm-wire__paymentscreator .m-wire--creator';
it('should open the Wire Payment modal', () => {
cy.visit('/plus');
cy.get(upgradeButton)
.should('be.visible')
.should('contain', 'Upgrade to Plus')
.click();
cy.get(wirePaymentsComponent).should('be.visible');
});
it('should automatically open the Wire Payment modal', () => {
cy.visit('/plus?i=yearly&c=tokens');
cy.get(wirePaymentsComponent).should('be.visible');
});
});
context('Pro Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const upgradeButton = 'm-pro--subscription .mf-button';
const wirePaymentsComponent = 'm-wire__paymentscreator .m-wire--creator';
it('should show a coming soon button', () => {
cy.visit('/pro');
cy.get(upgradeButton)
.should('be.visible')
.should('contain', 'Coming soon')
.click();
});
// it('should open the Wire Payment modal', () => {
//
// cy.visit('/pro');
//
// cy.get(upgradeButton)
// .should('be.visible')
// .should('contain', 'Upgrade to Pro')
// .click();
//
// cy.get(wirePaymentsComponent).should('be.visible');
// });
//
// it('should automatically open the Wire Payment modal', () => {
// cy.visit('/pro?i=yearly&c=tokens');
//
// cy.get(wirePaymentsComponent).should('be.visible');
// });
});
/**
* @author Ben Hayward
* @desc E2E testing for Minds Pro's pages.
*/
context('Pro Page', () => {
if (Cypress.env().pro_password) {
// required to run tests against pro user only.
const topBar = '.m-proChannel__topbar';
let categories = [
{ label: 'Technology', tag: '#technology' },
{ label: 'Food', tag: '#food' },
{ label: 'News', tag: '#news' },
];
let footerLinks = [
{ label: 'Minds', link: 'https://www.minds.com/' },
{ label: 'Careers', link: 'https://www.minds.com/careers' },
];
const proButton = 'data-minds-sidebar-admin-pro-button';
function resetSettings() {
cy.visit(`/pro/settings`);
cy.route('POST', '**/api/v2/pro/settings').as('settings');
cy.get('#title')
.focus()
.clear()
.type('Title');
cy.get('#headline')
.focus()
.clear()
.type('This is a headline');
cy.contains('Hashtags').click();
// remove all hashtags
removeInputs();
for (let i = 0; i < categories.length; i++) {
let cat = categories[i];
addTag(cat.label, cat.tag, i);
}
cy.contains('Footer').click();
cy.get('#footer_text')
.clear()
.type('This is the footer text');
// remove all footer links
removeInputs();
for (let i = 0; i < footerLinks.length; i++) {
let link = footerLinks[i];
addFooterLink(link.label, link.link, i);
}
cy.contains('Save')
.click()
.wait('@settings')
.then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body).to.deep.equal({ status: 'success' });
});
}
function removeInputs() {
cy.get(
'.m-draggableList__list .m-proSettings__field .m-proSettings__dragDropRow--input'
)
.should('be.visible')
.within($el => {
for (let i = $el.length - 1; i >= 0; i--) {
// flexInput. Start from the last one
let c = $el[i];
for (let j = 0; j < c.children.length; j++) {
// inputs and the X button
let cc = c.children[j];
if (cc.nodeName === 'I') {
// if it's the X button, click on it
cy.wrap(cc).click();
}
}
}
});
}
function addTag(label, tag, index) {
cy.contains('+ Add Tag').click();
cy.get(`#tag-label-${index}`)
.clear()
.type(label);
cy.get(`#tag-tag-${index}`)
.clear()
.type(tag);
}
function addFooterLink(label, link, index) {
cy.contains('Add Link').click();
cy.get(`#footer_link-title-${index}`)
.clear()
.type(label);
cy.get(`#footer_link-href-${index}`)
.clear()
.type(link);
}
before(() => {
cy.login(true, Cypress.env().pro_username, Cypress.env().pro_password);
// after logging in, we need to get to settings and set everything up
resetSettings();
// go to pro page
cy.visit(`/pro/${Cypress.env().pro_username}`);
cy.get(topBar);
});
beforeEach(() => {
cy.server();
cy.preserveCookies();
});
it('should load the feed tab', () => {
cy.route('GET', '**/api/v2/pro/content/*/activities/top**').as(
'activities'
);
cy.contains('Feed')
.click()
.wait('@activities')
.then(xhr => {
expect(xhr.status).to.equal(200);
});
});
it('should load the videos tab', () => {
cy.route('GET', '**/api/v2/pro/content/*/videos/top**').as('videos');
cy.contains('Videos')
.click()
.wait('@videos')
.then(xhr => {
expect(xhr.status).to.equal(200);
});
});
it('should load the images tab', () => {
cy.route('GET', '**/api/v2/pro/content/*/images/top**').as('images');
cy.contains('Images')
.click()
.wait('@images')
.then(xhr => {
expect(xhr.status).to.equal(200);
});
// should have sub-categories
cy.get('m-pro--channel--categories > .m-proChannel__category').each(
($el, $index) => {
let c = categories.slice(0);
c.unshift({ label: 'All', tag: '#all' });
expect($el.text()).to.contain(c[$index].label);
}
);
cy.get('m-pro--channel .m-overlay-modal').should('not.be.visible');
// click on tile
cy.get(
'.m-proChannelListContent__list li:first-child m-pro--channel-tile'
).click();
cy.wait(200);
// media modal should appear
cy.get('m-pro--channel .m-overlay-modal').should('be.visible');
// close media modal
cy.get('m-pro--channel .m-overlay-modal--close').click();
});
it('should load the articles tab', () => {
cy.route('GET', '**/api/v2/pro/content/*/blogs/top**').as('blogs');
cy.contains('Articles')
.click()
.wait('@blogs')
.then(xhr => {
expect(xhr.status).to.equal(200);
});
});
it('should load the groups tab', () => {
cy.route('GET', '**/api/v2/pro/content/*/groups/top**').as('groups');
cy.contains('Groups')
.click()
.wait('@groups')
.then(xhr => {
expect(xhr.status).to.equal(200);
});
});
it('should have a footer', () => {
// should have a footer text
cy.get('.m-proChannelFooter__text').contains('This is the footer text');
// should have footer links
cy.get(
'.m-proChannel__footer .m-proChannelFooter .m-proChannelFooter__link'
)
.should('be.visible')
.each(($el, $index) => {
expect($el.text()).to.contain(footerLinks[$index].label);
expect($el.attr('href')).to.contain(footerLinks[$index].link);
});
});
}
});
/**
* @author Ben Hayward
* @desc E2E testing for Minds Pro's settings.
*/
context('Pro Settings', () => {
if (Cypress.env().pro_password) {
// required to run tests against pro user only.
function data(str) {
return `[data-minds=${str}]`;
}
const activityContainer = 'minds-activity';
const sidebarMenu = data('sidebarMenuLinks');
const general = {
title: data('title'),
headline: data('headline'),
publish: data('publish'),
strings: {
title: 'Minds Pro E2E',
headline: 'This headline is a test',
},
};
const theme = {
textColor: data('textColor'),
primaryColor: data('primaryColor'),
plainBgColor: data('plainBgColor'),
schemeLight: data('schemeLight'),
schemeDark: data('schemeDark'),
aspectRatio: {
169: data('tileRatio_16:9'), // 16:9
1610: data('tileRatio_16:10'), // 16:10
43: data('tileRatio_4:3'), // 4:3
11: data('tileRatio_1:1'), // 1:1
},
strings: {
textColor: '#4690df',
primaryColor: '#cb7848',
plainBgColor: '#b4bbf0',
textColorRgb: 'rgb(70, 144, 223)',
primaryColorRgb: 'rgb(203, 120, 72)',
plainBgColorRgba: 'rgba(180, 187, 240, 0.627)',
resetColor: '#ffffff',
},
};
const assets = {
logo: data('logo'),
background: data('background'),
strings: {
logoFixture: '../../fixtures/avatar.jpeg',
backgroundFixture:
'../../fixtures/international-space-station-1776401_1920.jpg',
},
};
const hashtags = {
add: data('addHashtag'),
label0: data('tag__label--0'),
tag0: data('tag__tag--0'),
label1: data('tag__label--1'),
tag1: data('tag__tag--1'),
strings: {
label0: 'Label0',
label1: 'Label1',
tag0: '#hashtag0',
tag1: '#hashtag1',
},
};
const footer = {
text: data('footerText'),
add: data('addFooterLink'),
linkTitle: data('footerLink__title--0'),
linkHref: data('footerLink__href--0'),
strings: {
text: 'This is a footer',
linkTitle: 'Minds',
linkHref: 'https://www.minds.com/',
},
};
before(() => {
cy.login(true, Cypress.env().pro_username, Cypress.env().pro_password);
// Make a post
cy.route('POST', '**/api/v1/newsfeed').as('newsfeed');
cy.visit('/newsfeed/subscriptions');
cy.get('minds-newsfeed-poster textarea')
.click()
.type('Testing 1-2-3');
cy.get('minds-newsfeed-poster .m-posterActionBar__PostButton').click();
cy.wait('@newsfeed').then(xhr => {
expect(xhr.status).to.equal(200);
});
});
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route('POST', '**/api/v2/pro/settings').as('settings');
cy.visit('/pro/' + Cypress.env().pro_username + '/settings/general')
.location('pathname')
.should(
'eq',
'/pro/' + Cypress.env().pro_username + '/settings/general'
);
// ensure window is wide enough to find pro topbar links
cy.viewport(1300, 768);
});
it.skip('should update the title and headline', () => {
//enter data
cy.get(general.title)
.focus()
.clear()
.type(general.strings.title);
cy.get(general.headline)
.focus()
.clear()
.type(general.strings.headline);
saveAndPreview();
//check tab title
cy.title().should(
'eq',
general.strings.title + ' - ' + general.strings.headline + ' | Minds'
);
});
it('should allow the user to set theme colors', () => {
cy.get(sidebarMenu)
.contains('Theme')
.click();
// reset colors so changes will be submitted
cy.get(theme.textColor)
.click()
.clear()
.type(theme.strings.resetColor);
cy.get(theme.primaryColor)
.click()
.clear()
.type(theme.strings.resetColor);
cy.get(theme.plainBgColor)
.click()
.clear()
.type(theme.strings.resetColor);
save();
// set theme colors to be tested
cy.get(theme.textColor)
.click()
.clear()
.type(theme.strings.textColor);
cy.get(theme.primaryColor)
.click()
.clear()
.type(theme.strings.primaryColor);
cy.get(theme.plainBgColor)
.click()
.clear()
.type(theme.strings.plainBgColor);
saveAndPreview();
cy.get('.m-pro__searchBox input').should(
'have.css',
'background-color',
theme.strings.plainBgColorRgba
);
cy.get('.m-proChannelTopbar__navItem')
.contains('Videos')
.should('have.css', 'color', theme.strings.textColorRgb);
cy.get('.m-proChannelTopbar__navItem')
.contains('Feed')
.click();
// make window narrow enough to show hamburger icon/menu
cy.viewport('ipad-mini');
cy.get('.m-proHamburgerMenu__trigger')
.click()
.get('.m-proHamburgerMenu__item--active')
.should('have.css', 'color')
.and('eq', theme.strings.primaryColorRgb);
});
// Skipping until Emi changes feeds from 'top' to 'latest'
it.skip('should allow the user to set a dark theme for posts', () => {
cy.get(sidebarMenu)
.contains('Theme')
.click();
// Toggle radio to enable submit button
cy.get(theme.schemeLight).click({ force: true });
cy.get(theme.schemeDark).click({ force: true });
saveAndPreview();
cy.get('.m-proChannelTopbar__navItem')
.contains('Feed')
.click();
cy.get(activityContainer)
.should('have.css', 'background-color')
.and('eq', 'rgb(35, 35, 35)');
});
// Skipping until Emi changes feeds from 'top' to 'latest'
it.skip('should allow the user to set a light theme for posts', () => {
cy.get(sidebarMenu)
.contains('Theme')
.click();
// Toggle radio to enable submit button
cy.get(theme.schemeDark).click({ force: true });
cy.get(theme.schemeLight).click({ force: true });
saveAndPreview();
cy.get('.m-proChannelTopbar__navItem')
.contains('Feed')
.click();
cy.get(activityContainer)
.should('have.css', 'background-color')
.and('eq', 'rgb(255, 255, 255)');
});
it.skip('should allow the user to upload logo and background images', () => {
cy.get(sidebarMenu)
.contains('Assets')
.click();
cy.uploadFile(assets.logo, assets.strings.logoFixture, 'image/jpeg');
cy.uploadFile(
assets.background,
assets.strings.backgroundFixture,
'image/jpg'
);
saveAndPreview();
// cy.get('.m-proChannelTopbar__logo').should('have.attr', 'src', Cypress.env().url + '/fs/v1/pro/930229554033729554/logo/1574379135');
// cy.get(m-proChannel).should('have.attr', 'background-image', 'url(' + Cypress.env().url + '/fs/v1/banners/998753812159717376/fat/1563497464)');
});
it('should allow the user to set category hashtags', () => {
cy.get(sidebarMenu)
.contains('Hashtags')
.click();
cy.get(hashtags.add).click();
cy.get('m-draggableList')
.contains('clear')
.click({ multiple: true });
cy.get(hashtags.add).click();
cy.get(hashtags.label0)
.clear()
.type(hashtags.strings.label0);
cy.get(hashtags.tag0)
.clear()
.type(hashtags.strings.tag0);
cy.get(hashtags.add).click();
cy.get(hashtags.label1)
.clear()
.type(hashtags.strings.label1);
cy.get(hashtags.tag1)
.clear()
.type(hashtags.strings.tag1);
saveAndPreview();
//check the labels are present and clickable.
cy.contains(hashtags.strings.label0);
cy.contains(hashtags.strings.label1);
});
it('should allow the user to set footer', () => {
cy.get(sidebarMenu)
.contains('Footer')
.click();
// clear any existing footer links
cy.get(footer.add).click();
cy.get('m-draggableList')
.contains('clear')
.click({ multiple: true });
// add a new footer link
cy.get(footer.add).click();
cy.get(footer.linkHref)
.clear()
.type(footer.strings.linkHref);
cy.get(footer.linkTitle)
.clear()
.type(footer.strings.linkTitle);
// add footer text
cy.get(footer.text)
.clear()
.type(footer.strings.text);
saveAndPreview();
cy.contains(footer.strings.linkTitle)
.should('have.attr', 'href')
.should('contain', footer.strings.linkHref);
cy.get(footer.text).should('contain', footer.strings.text);
});
function save() {
//save and await response
cy.get('.m-shadowboxSubmitButton')
.contains('Save')
.click({ force: true })
.wait('@settings')
.then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body).to.deep.equal({ status: 'success' });
});
}
function saveAndPreview() {
save();
//go to pro page
cy.visit('/pro/' + Cypress.env().pro_username);
}
}
});
import generateRandomId from '../support/utilities';
context('Registration', () => {
const username = generateRandomId();
const password = `${generateRandomId()}0oA!`;
const email = 'test@minds.com';
const noSymbolPass = 'Passw0rd';
const welcomeText = "Welcome to Minds!";
const passwordDontMatch = "Passwords must match.";
const passwordInvalid = " Password must have more than 8 characters. Including uppercase, numbers, special characters (ie. !,#,@), and cannot have spaces. ";
const usernameField = 'minds-form-register #username';
const emailField = 'minds-form-register #email';
const passwordField = 'minds-form-register #password';
const password2Field = 'minds-form-register #password2';
const checkbox = '[data-cy=data-minds-accept-tos-input]';
const submitButton = 'minds-form-register .mdl-card__actions button';
beforeEach(() => {
cy.clearCookies();
cy.visit('/login');
cy.location('pathname').should('eq', '/login');
cy.server();
cy.route("POST", "**/api/v1/register").as("register");
});
after(() => {
cy.visit('/login');
cy.location('pathname').should('eq', '/login');
cy.login(false, username, password);
cy.deleteUser(username, password);
cy.clearCookies();
})
it('should allow a user to register', () => {
//type values
cy.get(usernameField)
.focus()
.type(username);
cy.get(emailField)
.focus()
.type(email);
cy.get(passwordField)
.focus()
.type(password);
cy.wait(500);
cy.get(password2Field)
.focus()
.type(password);
cy.get(checkbox)
.click({force: true});
//submit
cy.get(submitButton)
.click()
.wait('@register').then((xhr) => {
expect(xhr.status).to.equal(200);
});
//onboarding modal shown
cy.contains(welcomeText);
});
it('should display an error if password is invalid', () => {
cy.get(usernameField)
.focus()
.type(generateRandomId());
cy.get(emailField)
.focus()
.type(email);
cy.get(passwordField)
.focus()
.type(noSymbolPass);
cy.wait(500);
cy.get(password2Field)
.focus()
.type(noSymbolPass);
cy.get(checkbox)
.click({force: true});
//submit
cy.get(submitButton)
.click()
.wait('@register').then((xhr) => {
expect(xhr.status).to.equal(200);
});
cy.scrollTo('top');
cy.contains(passwordInvalid);
});
it('should display an error if passwords do not match', () => {
cy.get(usernameField)
.focus()
.type(generateRandomId());
cy.get(emailField)
.focus()
.type(email);
cy.get('minds-form-register #password')
.focus()
.type(password);
cy.wait(500);
cy.get(password2Field)
.focus()
.type(password + '!');
cy.get(checkbox)
.click({force: true});
//submit
cy.get(submitButton).click();
cy.scrollTo('top');
cy.contains(passwordDontMatch);
});
})
context('Remind', () => {
const remindText = 'remind test text';
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
cy.visit(`/${Cypress.env().username}`);
});
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route("POST", "**/api/v2/newsfeed/remind/*").as("postRemind");
});
it('should allow a user to remind their post', () => {
//post
cy.post("test!!");
//open remind composer
cy.get('minds-button-remind > a')
.first()
.click();
//fill out text box in modal
cy.get('.m-modal-remind-composer textarea')
.focus()
.clear()
.type(remindText);
//post remind.
cy.get('.m-modal-remind-composer-send i')
.click()
.wait('@postRemind').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
});
});
context('Subscription', () => {
const user = 'minds';
const subscribeButton = 'minds-button-subscribe > button';
const messageButton = 'm-messenger--channel-button > button';
const userDropdown = 'minds-button-user-dropdown > button';
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route("POST", "**/api/v1/subscribe/*").as("subscribe");
cy.route("DELETE", "**/api/v1/subscribe/*").as("unsubscribe");
cy.visit(`/${user}/`);
cy.location('pathname')
.should('eq', `/${user}/`);
});
it('should allow a user to subscribe to another', () => {
subscribe();
});
it('should allow a user to unsubscribe',() => {
unsubscribe();
});
function subscribe() {
cy.get(subscribeButton)
.click()
.wait('@subscribe').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
cy.get(messageButton).should('be.visible')
}
function unsubscribe() {
cy.get(userDropdown).click();
cy.contains('Unsubscribe')
.click()
.wait('@unsubscribe').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
});
cy.get(subscribeButton).should('be.visible');
}
});
context('Topbar', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
});
beforeEach(()=> {
cy.preserveCookies();
});
it("clicking on the dropdown on the right should allow to go to the user's channel", () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get('m-user-menu .m-user-menu__Dropdown li')
.contains('View Channel')
.click();
cy.location('pathname').should('eq', `/${Cypress.env().username}/`);
});
it('clicking on the dropdown on the right should allow to go to settings', () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get('m-user-menu .m-user-menu__Dropdown li')
.contains('Settings')
.click();
cy.location('pathname').should('eq', '/settings/general');
});
it('clicking on the dropdown on the right should allow to go to the boost console', () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get("m-user-menu .m-user-menu__Dropdown li:contains('Boost Console')")
.click();
cy.location('pathname').should('contain', '/boost/console/newsfeed/');
});
it('clicking on the dropdown on the right should allow to go to the help desk', () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get("m-user-menu .m-user-menu__Dropdown li:contains('Help Desk')")
.click();
cy.location('pathname').should('eq', '/help');
});
it('clicking on the dropdown on the right should redirect to /canary', () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get("m-user-menu .m-user-menu__Dropdown li:contains('Canary')")
.click();
cy.location('pathname').should('eq', '/canary');
});
it('clicking on the dropdown on the right should allow to toggle Dark Mode', () => {
// open the menu
cy.get('m-user-menu .m-user-menu__Anchor').click();
cy.get('body.m-theme__light').should('be.visible');
cy.get("m-user-menu .m-user-menu__Dropdown li:contains('Dark Mode')")
.click();
cy.get('body.m-theme__dark').should('be.visible');
cy.get('m-user-menu .m-user-menu__Dropdown li')
.contains('Light Mode')
.click();
cy.get('body.m-theme__light').should('be.visible');
cy.get('m-user-menu .m-user-menu__Anchor').click({ force: true });
});
it('clicking on the bulb on the topbar should redirect to /newsfeed/subscriptions', () => {
cy.get('.m-v2-topbarNavItem__Logo img').should('be.visible');
cy.get('.m-v2-topbarNavItem__Logo').click();
cy.location('pathname').should('eq', '/newsfeed/subscriptions');
});
it('clicking on the bell should open the notifications dropdown, and allow to view all notifications by redirecting to /notifications', () => {
cy.get('.m-v2-topbar__UserMenu m-notifications--flyout').should('not.be.visible');
cy.get('.m-v2-topbar__UserMenu a.m-notifications--topbar-toggle--icon')
.should('be.visible')
.click();
cy.get('.m-v2-topbar__UserMenu m-notifications--flyout').should('be.visible');
cy.get('.m-notifications--flyout--bottom-container a')
.click();
cy.location('pathname').should('eq', '/notifications');
});
})
context('Upgrades page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
cy.visit('/upgrades');
});
it('should scroll to upgrades table', () => {
cy.viewport(1200, 600); // Only on desktop
const scrollButton = '[data-cy="m-upgrades__upgrade-now-button"]';
const heading = '.m-upgradesUpgradeOptions__header h2';
cy.get(scrollButton)
.should('contain', 'Upgrade now')
.click();
cy.wait(1500);
cy.isInViewport(heading);
});
// TODO: Toggles tests (make them testable)
it('should have the ability to trigger Buy Tokens modal', () => {
const tokensInput = 'm-blockchain--purchase input[name=amount]';
const buyTokensButton =
'm-blockchain--purchase .m-blockchainTokenPurchase__action .mf-button';
const anyBuyTokensModal =
'm-blockchain--purchase m-modal .m-modal-container';
cy.get(tokensInput)
.focus()
.clear()
.type('0');
cy.get(buyTokensButton).should('be.disabled');
cy.get(tokensInput)
.focus()
.clear()
.type('1');
cy.get(buyTokensButton)
.should('not.be.disabled')
.click();
cy.get('.m-get-metamask--cancel-btn.m-btn').click();
cy.get(anyBuyTokensModal).should('be.visible');
});
it('should have the ability to trigger Buy Eth modal', () => {
const buyEthLink =
'm-blockchain--purchase .m-blockchainTokenPurchase__ethRate a';
const buyEthModal = 'm-blockchain__eth-modal .m-modal-container';
cy.get(buyEthLink).click();
cy.get(buyEthModal).should('be.visible');
});
it('should navigate to Plus and trigger a Wire', () => {
const upgradeButton = cy.get(
'[data-cy="m-upgradeOptions__upgrade-to-plus-button"]'
);
upgradeButton.click();
cy.location('pathname').should('contain', '/plus');
});
it('should navigate to Pro and trigger a Wire', () => {
const upgradeButton = cy.get(
'[data-cy="m-upgradeOptions__upgrade-to-pro-button"]'
);
upgradeButton.click();
cy.location('pathname').should('contain', '/pro');
});
it('should navigate to Nodes', () => {
const upgradeButton = cy.get(
'[data-cy="m-upgradeOptions__contact-us-nodes-button"]'
);
upgradeButton.click();
cy.location('pathname').should('contain', '/nodes');
});
});
/**
* @author Ben Hayward
* @create date 2019-08-11 23:46:00
* @modify date 2019-08-11 23:46:00
* @desc Spec tests for Wire transactions.
*/
import generateRandomId from "../../support/utilities";
// Issue to re-enable https://gitlab.com/minds/front/issues/1846
context.skip('Wire Creator', () => {
const receiver = {
username: generateRandomId(),
password: generateRandomId()+'F!',
}
const sendAmount = 5000;
const wireButton = 'm-wire-channel > div > button';
const sendButton = '.m-wire--creator-section--last > div > button';
const modal = 'm-overlay-modal > div.m-overlay-modal';
before(() => {
cy.newUser(receiver.username, receiver.password);
cy.logout();
});
beforeEach(()=> {
cy.preserveCookies();
cy.login(true);
});
afterEach(() => {
// cy.login(true, receiver.username, receiver.password);
cy.visit(`/${Cypress.env().username}`);
// Click profile wire button
cy.get(wireButton).click();
cy.wait(2000);
// Click send button
cy.get(sendButton).click();
cy.wait(5000);
//Make sure modal is hidden after 5 seconds.
cy.get(modal).should('be.hidden');
});
it('should allow a user to send a wire to another user', () => {
// Visit users page.
cy.visit(`/${receiver.username}`);
// Click profile wire button
cy.get(wireButton).click();
cy.wait(2000);
// Click send button
cy.get(sendButton).click();
cy.wait(5000);
//Make sure modal is hidden after 5 seconds.
cy.get(modal).should('be.hidden');
});
})
context('Pay Product Page', () => {
before(() => {
cy.getCookie('minds_sess').then(sessionCookie => {
if (!sessionCookie) {
return cy.login(true);
}
});
});
beforeEach(() => {
cy.preserveCookies();
});
const monetizeChannelButton = '.m-marketing__mainWrapper .mf-button';
it('should have a monetize channel button', () => {
cy.visit('/pay');
cy.get(monetizeChannelButton)
.should('be.visible')
.should('contain', 'Monetize your channel')
.click();
cy.location('pathname').should(
'contains',
'/wallet/tokens/contributions'
);
});
});
This diff is collapsed.
......@@ -18,3 +18,5 @@ import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
Cypress.Cookies.debug(true);
/**
* @author Ben Hayward
* @create date 2019-08-10 00:38:46
* @modify date 2019-08-10 00:38:46
* @desc Space to put utilities and helper functions without cluttering up commands.js
*/
/**
* @returns a random 21 character string
*/
const generateRandomId = () => {
return Math.random().toString(36).substring(2, 15)
+ Math.random().toString(36).substring(2, 15);
}
export default generateRandomId;
......@@ -10,7 +10,8 @@ module.exports = function (config) {
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
require('@angular-devkit/build-angular/plugins/karma'),
require('karma-mocha-reporter'),
],
// webpack: { node: { fs: 'empty', } },
client:{
......@@ -21,7 +22,7 @@ module.exports = function (config) {
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
reporters: ['mocha'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
......
This diff is collapsed.
This diff is collapsed.
import { trigger, style, animate, transition, keyframes } from '@angular/animations';
import {
trigger,
style,
animate,
transition,
keyframes,
} from '@angular/animations';
export const animations: any[] = [
trigger('foolishIn', [
transition('* => *', [
style({ opacity: 0 }),
animate(2000, keyframes([
style({ opacity: 0, transformOrigin: '50% 50%', transform: 'scale(0, 0) rotate(360deg)', offset: 0.000 }),
style({ opacity: 1, transformOrigin: '0% 100%', transform: 'scale(0.5, 0.5) rotate(0deg)', offset: 0.066 }),
style({ opacity: 1, transformOrigin: '100% 100%', transform: 'scale(0.5, 0.5) rotate(0deg)', offset: 0.132 }),
style({ opacity: 1, transformOrigin: '0%', transform: 'scale(0.5, 0.5) rotate(0deg)', offset: 0.198 }),
style({ opacity: 1, transformOrigin: '0% 0%', transform: 'scale(0.5, 0.5) rotate(0deg)', offset: 0.264 }),
style({ opacity: 1, transformOrigin: '50% 50%', transform: 'scale(1, 1) rotate(0deg)', offset: 0.330 }),
style({ opacity: 1, offset: 0.660 }),
style({ opacity: 0, offset: 1.000 }),
]))
])
])
animate(
2000,
keyframes([
style({
opacity: 0,
transformOrigin: '50% 50%',
transform: 'scale(0, 0) rotate(360deg)',
offset: 0.0,
}),
style({
opacity: 1,
transformOrigin: '0% 100%',
transform: 'scale(0.5, 0.5) rotate(0deg)',
offset: 0.066,
}),
style({
opacity: 1,
transformOrigin: '100% 100%',
transform: 'scale(0.5, 0.5) rotate(0deg)',
offset: 0.132,
}),
style({
opacity: 1,
transformOrigin: '0%',
transform: 'scale(0.5, 0.5) rotate(0deg)',
offset: 0.198,
}),
style({
opacity: 1,
transformOrigin: '0% 0%',
transform: 'scale(0.5, 0.5) rotate(0deg)',
offset: 0.264,
}),
style({
opacity: 1,
transformOrigin: '50% 50%',
transform: 'scale(1, 1) rotate(0deg)',
offset: 0.33,
}),
style({ opacity: 1, offset: 0.66 }),
style({ opacity: 0, offset: 1.0 }),
])
),
]),
]),
];
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
export * from './text-input-autocomplete.module';
export { TextInputAutocompleteMenuComponent } from './text-input-autocomplete-menu.component';
m-post-autocomplete-item-renderer {
.m-postAutocompleteItemRenderer__avatar {
margin-right: 4px;
height: 24px;
border-radius: 50%;
}
}
This diff is collapsed.
export class CaptchaService {
}
export class CaptchaService {}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.