Skip to content
Commits on Source (158)
......@@ -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",
......
......@@ -38,3 +38,5 @@ cypress/videos
!/.drone.yml
!/.gitlab
!/.githooks
!/.prettierrc
!.gitattributes
image: markharding/minds-front-base
services:
- docker:dind
stages:
- test
- build
- prepare
- review
- deploy:staging
- test:e2e
- qa
- deploy:canary
- deploy:production
- cleanup
......@@ -34,9 +31,13 @@ lint:
- prettier --check "src/**/*.scss"
- prettier --check "src/**/*.html"
e2e:chrome:
############
# QA Stage #
############
qa:e2e:
image: cypress/browsers:chrome67
stage: test:e2e
stage: qa
variables:
CYPRESS_INSTALL_BINARY: 3.4.1
script:
......@@ -44,12 +45,14 @@ e2e:chrome:
- >
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
- $(npm bin)/cypress run --browser chrome --record --key $CYPRESS_RECORD_ID --config CYPRESS_baseUrl=$E2E_DOMAIN,production=$PRODUCTION
artifacts:
when: always
paths:
......@@ -61,6 +64,17 @@ e2e:chrome:
- 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 #
###############
......@@ -137,6 +151,8 @@ build:production:i18n:
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/.
......@@ -162,6 +178,8 @@ prepare:review:sentry:
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/.
......@@ -244,6 +262,8 @@ review:stop:
.deploy: &deploy
image: minds/ci:latest
services:
- docker:dind
script:
## Sync assets with CDN
- aws s3 sync dist $S3_REPOSITORY_URL
......@@ -306,6 +326,7 @@ deploy:production:
cleanup:review: # We stop the review site after the e2e tests have run
<<: *cleanup_review
stage: cleanup
when: manual
except:
refs:
- master
......
......@@ -16,10 +16,7 @@
"main": "src/main.ts",
"tsConfig": "src/tsconfig.app.json",
"polyfills": "src/polyfills.ts",
"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/material-design-icons/iconfont/material-icons.css",
......@@ -36,10 +33,10 @@
"optimization": true,
"outputHashing": "all",
"sourceMap": {
"hidden": true,
"scripts": true,
"styles": true
},
"hidden": true,
"scripts": true,
"styles": true
},
"extractCss": true,
"namedChunks": false,
"aot": true,
......@@ -52,6 +49,14 @@
"with": "src/environments/environment.prod.ts"
}
]
},
"hmr": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.hmr.ts"
}
]
}
}
},
......@@ -63,6 +68,10 @@
"configurations": {
"production": {
"browserTarget": "v5.x:build:production"
},
"hmr": {
"hmr": true,
"browserTarget": "v5.x:build:hmr"
}
}
},
......@@ -83,22 +92,14 @@
"node_modules/medium-editor/dist/js/medium-editor.min.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/**"]
}
}
}
......@@ -118,12 +119,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/**"]
}
}
}
......@@ -132,11 +129,11 @@
"defaultProject": "v5.x",
"schematics": {
"@schematics/angular:component": {
"prefix": "app",
"prefix": "m",
"styleext": "scss"
},
"@schematics/angular:directive": {
"prefix": "app"
"prefix": "m"
}
}
}
#!/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
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');
});
});
......@@ -2,71 +2,77 @@
context('Blogs', () => {
before(() => {
cy.clearCookies();
cy.getCookie('minds_sess')
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
.then((sessionCookie) => {
if (sessionCookie === null) {
return cy.login(true);
}
});
});
beforeEach(()=> {
beforeEach(() => {
cy.preserveCookies();
cy.server();
cy.route('POST', '**/api/v1/blog/new').as('postBlog');
cy.route('POST', '**/api/v1/media**').as('postMedia');
cy.route('GET', '**/api/v1/blog/**').as('getBlog');
cy.route('DELETE', '**/api/v1/blog/**').as('deleteBlog');
cy.visit('/newsfeed/global/top')
.location('pathname')
.should('eq', '/newsfeed/global/top');
});
it('should not be able to create a new blog if no title or banner are specified', () => {
cy.visit('/blog/edit/new');
cy.get('.m-button--submit').click();
cy.get('.m-blog--edit--error').contains('Error: You must provide a title');
cy.get('minds-textarea .m-editor').type('Title');
cy.get('.m-button--submit').click();
cy.get('.m-blog--edit--error').contains('Error: You must upload a banner');
})
it('should be able to create a new blog', () => {
// upload avatar first
const uploadAvatar = () => {
cy.visit(`/${Cypress.env().username}`);
cy.get('.m-channel--name .minds-button-edit button:first-child').click();
cy.uploadFile('.minds-avatar input[type=file]', '../fixtures/avatar.jpeg', 'image/jpg');
cy.uploadFile(
'.minds-avatar input[type=file]',
'../fixtures/avatar.jpeg',
'image/jpg'
);
cy.get('.m-channel--name .minds-button-edit button:last-child').click();
};
// create blog
const createBlogPost = (title, body, nsfw = false, schedule = false) => {
cy.visit('/blog/edit/new');
cy.uploadFile('.minds-banner input[type=file]', '../fixtures/international-space-station-1776401_1920.jpg', 'image/jpg');
cy.get('minds-textarea .m-editor').type('Title');
cy.uploadFile(
'.minds-banner input[type=file]',
'../fixtures/international-space-station-1776401_1920.jpg',
'image/jpg'
);
cy.get('m-inline-editor .medium-editor-element').type('Content\n');
cy.get('minds-textarea .m-editor').type(title);
cy.get('m-inline-editor .medium-editor-element').type(body);
// click on plus button
// // click on plus button
// cy.get('.medium-editor-element > .medium-insert-buttons > button.medium-insert-buttons-show').click();
// click on camera
// // click on camera
// cy.get('ul.medium-insert-buttons-addons > li > button.medium-insert-action:first-child').contains('photo_camera').click();
// upload the image
// cy.uploadFile('.medium-media-file-input', '../fixtures/international-space-station-1776401_1920.jpg', 'image/jpg');
cy.uploadFile('.medium-media-file-input', '../fixtures/international-space-station-1776401_1920.jpg', 'image/jpg')
.wait('@postMedia').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
});
// open license dropdown & select first license
cy.get('.m-license-info select').select('All rights reserved');
// click on hashtags dropdown
cy.get('.m-category-info m-hashtags-selector .m-dropdown--label-container').click();
cy.get(
'.m-category-info m-hashtags-selector .m-dropdown--label-container'
).click();
// select #ART
cy.get('.m-category-info m-dropdown m-form-tags-input > div > span').contains('#art').click();
cy.get('.m-category-info m-dropdown m-form-tags-input > div > span')
.contains('#art')
.click();
// type in another hashtag manually
cy.get('.m-category-info m-hashtags-selector m-form-tags-input input').type('hashtag{enter}').click();
cy.get('.m-category-info m-hashtags-selector m-form-tags-input input')
.type('hashtag{enter}')
.click();
// click away
cy.get('.m-category-info m-hashtags-selector .minds-bg-overlay').click();
......@@ -75,51 +81,221 @@ context('Blogs', () => {
cy.get('.m-visibility-info select').select('Loggedin');
// open metadata form
cy.get('.m-blog-edit--toggle-wrapper .m-blog-edit--toggle').contains('Metadata').click();
cy.get('.m-blog-edit--toggle-wrapper .m-blog-edit--toggle')
.contains('Metadata')
.click();
// set url slug
cy.get('.m-blog-edit--field input[name=slug]').type('123');
// set meta title
cy.get('.m-blog-edit--field input[name=custom_meta_title]').type('Test');
// set meta description
cy.get('.m-blog-edit--field textarea[name=custom_meta_description]').type('This is a test blog');
cy.get('.m-blog-edit--field textarea[name=custom_meta_description]').type(
'This is a test blog'
);
// set meta author
cy.get('.m-blog-edit--field input[name=custom_meta_author]').type('Minds Test');
cy.get('.m-blog-edit--field input[name=custom_meta_author]').type(
'Minds Test'
);
if (nsfw) {
cy.get('.m-mature-info a').click();
cy.get('.m-mature-info a span').contains('Mature content');
}
if (schedule) {
cy.get('.m-poster-date-selector__input').click();
cy.get(
'td.c-datepicker__day-body.c-datepicker__day--selected + td'
).click();
cy.get('a.c-btn.c-btn--flat.js-ok').click();
// get setted date to compare
let scheduledDate;
cy.get('div.m-poster-date-selector__input div.m-tooltip--bubble')
.invoke('text')
.then(text => {
scheduledDate = text;
});
}
cy.get('.m-button--submit')
.click({ force: true }) // TODO: Investigate why disabled flag is being detected
.wait('@postBlog').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
})
.wait('@getBlog').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
expect(xhr.response.body).to.have.property('blog');
});
// set as nsfw
cy.get('.m-mature-info a').click();
cy.get('.m-mature-info a span').contains('Mature content');
cy.location('pathname')
.should('contains', `/${Cypress.env().username}/blog`);
cy.server();
cy.route("POST", "**/api/v1/blog/new").as("postBlog");
cy.route("GET", "**/api/v1/blog/**").as("getBlog");
cy.get('.m-blog--title').contains(title);
cy.get('.minds-blog-body p').contains(body);
cy.get('.m-license-info span').contains('all-rights-reserved');
cy.get('.m-button--submit').click({ force: true }); // TODO: Investigate why disabled flag is being detected
if (schedule) {
cy.wait(1000);
cy.wait('@postBlog').then((xhr) => {
cy.get('div.m-blog-container div.mdl-grid div.minds-body span')
.invoke('text')
.then(text => {
const time_created = new Date(text).getTime();
scheduledDate = new Date(scheduledDate).getTime();
expect(scheduledDate).to.equal(time_created);
});
}
};
const deleteBlogPost = () => {
cy.get('m-post-menu button.minds-more').click();
cy.get('m-post-menu ul.minds-dropdown-menu li')
.contains('Delete')
.click();
cy.get('m-post-menu m-modal-confirm .mdl-button--colored').click();
cy.wait('@deleteBlog').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
expect(xhr.response.body.status).to.equal('success');
});
};
const editBlogPost = (title, body) => {
cy.location('pathname').should(
'contains',
`/${Cypress.env().username}/blog`
);
cy.get('m-post-menu').click();
cy.get('.minds-dropdown-menu li')
.first()
.click();
cy.location('pathname').should('contains', '/blog/edit');
cy.get('minds-textarea .m-editor').type(title);
cy.get('m-inline-editor .medium-editor-element').type(body);
cy.wait('@getBlog').then((xhr) => {
cy.get('.m-button--submit').click();
cy.wait('@postBlog').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal("success");
expect(xhr.response.body).to.have.property("blog");
expect(xhr.response.body.status).to.equal('success');
cy.wait('@getBlog').then(xhr => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.equal('success');
expect(xhr.response.body).to.have.property('blog');
});
});
cy.location('pathname')
.should('contains', `/${Cypress.env().username}/blog`);
cy.location('pathname').should(
'contains',
`/${Cypress.env().username}/blog`
);
cy.get('.m-blog--title').contains('Title');
cy.get('.minds-blog-body p').contains('Content');
cy.get('.m-blog--title').contains(title);
cy.get('.minds-blog-body p').contains(body);
};
cy.get('.m-license-info span').contains('all-rights-reserved');
it('should not be able to create a new blog if no title or banner are specified', () => {
cy.visit('/blog/edit/new');
cy.get('.m-button--submit').click();
cy.get('.m-blog--edit--error').contains('Error: You must provide a title');
cy.get('minds-textarea .m-editor').type('Title');
cy.get('.m-button--submit').click();
cy.get('.m-blog--edit--error').contains('Error: You must upload a banner');
});
// cleanup
it('should be able to create a new blog', () => {
const title = 'Title';
const body = 'Content';
//open dropdown
cy.get('m-post-menu button.minds-more').click();
cy.get('m-post-menu ul.minds-dropdown-menu li').contains('Delete').click();
cy.get('m-post-menu m-modal-confirm .mdl-button--colored').click();
uploadAvatar();
createBlogPost(title, body, true);
deleteBlogPost();
});
/**
* Skipping until the scheduling options are visible on sandboxes
* currently they are not, missing setting perhaps?
*/
it.skip('should be able to create a new scheduled blog', () => {
uploadAvatar();
createBlogPost('Title', 'Content', true, true);
deleteBlogPost();
});
/**
* Skipping until sandbox behaves consistently as currently when posting,
* on the sandbox it does not update the newsfeed and channel straight away as it does on prod.
*/
it.skip('should create an activity for the blog post', () => {
const identifier = Math.floor(Math.random() * 100);
const title = 'Test Post for Activity ' + identifier;
const body = 'Some content here ' + identifier;
createBlogPost(title, body);
cy.visit(`/${Cypress.env().username}`);
//:nth-child(3) > .mdl-card > .m-rich-embed > minds-rich-embed > .m-rich-embed-src > .meta > .m-rich-embed--title
cy.get('minds-activity:first .m-blurb').contains(body);
cy.get('minds-activity:first .m-rich-embed--title')
.first()
.contains(title);
cy.get('minds-activity:first .thumbnail')
.should('have.attr', 'href')
.then(href => {
cy.visit(href);
});
cy.location('pathname').should(
'contains',
`/${Cypress.env().username}/blog`
);
deleteBlogPost();
cy.location('pathname').should(
'contains',
`/blog/owner`
);
});
})
})
/**
* Skipping until sandbox behaves consistently as currently when posting,
* on the sandbox it does not update the newsfeed and channel straight away as it does on prod.
*/
it.skip('should update the activity when blog is updated', () => {
const identifier = Math.floor(Math.random() * 100);
const title = 'Test Post for Activity ' + identifier;
const body = 'Some content here ' + identifier;
createBlogPost(title, body);
cy.visit(`/${Cypress.env().username}`);
cy.get('minds-activity:first .m-blurb').contains(body);
cy.get('minds-activity:first .m-rich-embed--title')
.first()
.contains(title);
cy.get('minds-activity:first .thumbnail')
.should('have.attr', 'href')
.then(href => {
cy.visit(href);
});
const newtitle = title + ' changed';
const newbody = body + ' changed';
editBlogPost(newtitle, newbody);
cy.visit(`/${Cypress.env().username}`);
cy.get('minds-activity:first .m-blurb').contains(body);
cy.get('minds-activity:first .m-rich-embed--title')
.first()
.contains(title);
cy.get('minds-activity:first .thumbnail')
.should('have.attr', 'href')
.then(href => {
cy.visit(href);
});
deleteBlogPost();
});
});
/**
* @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..." + Math.random().toString(36);
const postContent = "Test boost, please reject..." + generateRandomId();
before(() => {
cy.getCookie('minds_sess')
......@@ -8,27 +14,24 @@ context('Boost Console', () => {
return cy.login(true);
}
});
newBoost(postContent, 500);
});
beforeEach(() => {
cy.preserveCookies();
cy.visit('/newsfeed/subscribed');
newBoost(postContent, 100);
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.visit('/boost/console/newsfeed/history');
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) .m-mature-message span')
.contains(postContent);
});
it('should allow a revoke a boost', () => {
navToConsole();
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.should('not.contain', 'revoked');
......@@ -39,15 +42,42 @@ context('Boost Console', () => {
.contains('revoked');
});
function navToConsole() {
cy.visit('/boost/console/newsfeed/history');
cy.location('pathname')
.should('eq', `/boost/console/newsfeed/history`);
}
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')
......@@ -61,7 +91,6 @@ context('Boost Console', () => {
.click();
cy.wait('@boostPost').then((xhr) => {
cy.log(xhr);
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
......
context('Boost Creation', () => {
const duplicateError = "There's already an ongoing boost for this entity";
const postContent = "Test boost, please reject..." + Math.random().toString(36).substring(8);
const nonParticipationError = 'Boost target should participate in the Rewards program.'
/**
* @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.server();
})
beforeEach(() => {
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.route("GET", '**/api/v2/boost/prepare/**').as('prepare');
cy.route("POST", '**/api/v2/boost/activity/**').as('activity');
cy.route("GET", '**/api/v2/blockchain/wallet/balance*').as('balance');
cy.route("GET", '**/api/v2/search/suggest/**').as('suggest');
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 redirect a user to buy tokens when clicked', () => {
openTopModal();
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);
});
cy.get('m-boost--creator-payment-methods li h5 span')
.contains('Buy Tokens')
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.location('pathname', { timeout: 30000 })
.should('eq', `/token`);
cy.get('m-boost-console-card:nth-child(1) div.m-boost-card--manager-item.m-boost-card--state')
.contains('revoked');
});
it('should allow a user to make an offchain boost for 5000 tokens', () => {
cy.post(postContent);
openTopModal();
cy.get('.m-boost--creator-section-amount input')
.type(5000);
cy.get('m-overlay-modal > div.m-overlay-modal > m-boost--creator button')
it('should load show the user content for newsfeed boosts', () => {
cy.route("GET", "**/feeds/container/*/activities**").as("activities");
cy.contains('Create a Boost')
.click()
.wait('@prepare').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
}).wait('@activity').then((xhr) => {
.location('pathname')
.should('eq', `/boost/console/newsfeed/create`)
.wait('@activities').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')
});
it('should error if the boost is a duplicate', () => {
openTopModal();
cy.get('.m-boost--creator-section-amount input')
.type(5000);
})
cy.get('m-overlay-modal > div.m-overlay-modal > m-boost--creator button')
.click()
.wait('@prepare').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
}).wait('@activity').then((xhr) => {
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);
expect(xhr.response.body.status).to.deep.equal("error");
});
cy.get('[data-cy=data-minds-boost-creation-error]')
.contains(duplicateError);
});
it('should display an error if boost offer receiver has not signed up for rewards', () => {
openTopModal();
})
cy.get('h4')
.contains('Offers')
.click();
cy.get('m-boost--creator-p2p-search .m-boost--creator-wide-input input')
.type("minds").wait('@suggest').then((xhr) => {
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);
expect(xhr.response.body.status).to.deep.equal("success");
});
cy.get('.m-boost--creator-autocomplete--results .m-boost--creator-autocomplete--result-content')
.first()
.click({force: true});
})
cy.get('[data-cy=data-minds-boost-creation-error]')
.contains(nonParticipationError);
});
function newBoost(text, views) {
cy.server();
cy.route("POST", '**/api/v2/boost/**').as('boostPost');
cy.visit('/newsfeed/subscribed');
cy.post(text);
function openTopModal() {
cy.get('#boost-actions')
.first()
.click()
.wait('@balance').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body.status).to.deep.equal("success");
});
.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')
}
})
context('Boost Impressions', () => {
// 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) => {
......@@ -7,37 +8,40 @@ context('Boost Impressions', () => {
return cy.login(true);
}
});
cy.visit('/newsfeed/subscriptions');
cy.location('pathname')
.should('eq', `/newsfeed/subscriptions`);
});
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', () => {
//stub endpoint
cy.server();
cy.route("POST", "**/api/v2/analytics/views/activity/*").as("analytics");
//load, scroll, wait to trigger analytics
cy.scrollTo(0, 500);
//smooth scroll
cy.scrollTo('0', '1%', { duration: 100 });
//assert
cy.wait('@analytics').then((xhr) => {
expect(xhr.status).to.equal(200);
expect(xhr.response.body).to.deep.equal({ status: 'success' });
});
});
it('should register views on boost rotate', () => {
//stub endpoint
cy.server();
cy.route("POST", "**/api/v2/analytics/views/boost/*").as("analytics");
//rotate forward and wait to trigger analytics
cy.get('m-newsfeed--boost-rotator > div > ul > li:nth-child(3) > i')
cy.get('m-newsfeed--boost-rotator')
.find('chevron_right')
.click();
//assert
......@@ -47,7 +51,8 @@ context('Boost Impressions', () => {
});
//rotate forward and wait to trigger analytics
cy.get('m-newsfeed--boost-rotator > div > ul > li:nth-child(2) > i')
cy.get('m-newsfeed--boost-rotator')
.find('chevron_left')
.click();
//assert
......
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();
});
});
});
context('Channel', () => {
// skipped until feat release
context.skip('Channel', () => {
before(() => {
cy.getCookie('minds_sess')
.then((sessionCookie) => {
......
// 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')");
});
});
......@@ -6,7 +6,9 @@ context('Discovery', () => {
return cy.login(true);
}
});
cy.visit('/newsfeed/global/top');
cy.visit('/newsfeed/global/top')
.location('pathname')
.should('eq', '/newsfeed/global/top');
});
beforeEach(()=> {
......
......@@ -32,17 +32,21 @@ context('Groups', () => {
// 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();
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');
......
......@@ -52,6 +52,7 @@ context('Messenger', () => {
after(() => {
cy.deleteUser(testUsername, testPassword);
cy.clearCookies({log: true})
});
it('should allow a new user to set a password and send a message', () => {
......
This diff is collapsed.