test: setup cypress (#3152)

This commit is contained in:
Alexis Saettler
2020-03-20 08:17:59 +01:00
committed by GitHub
parent 3ee61a9ea0
commit de45518957
74 changed files with 1298 additions and 1037 deletions
BIN
View File
Binary file not shown.
+3 -8
View File
@@ -6,18 +6,13 @@ jobs:
- template: step-prepare-environment.yml
- template: step-composer-install.yml
- task: Cache@2
inputs:
key: yarn-v1 | yarn.lock
restoreKeys: |
yarn-v1
path: $(YARN_CACHE_FOLDER)
displayName: Cache Yarn packages
- template: step-cache-yarn.yml
- script: yarn inst
displayName: 'yarn install'
# Update js and css assets eventually
- script: yarn lint
- script: yarn lint:all
displayName: 'Check js and vue lint'
- bash: |
source scripts/ci/fixsecrets.sh
+6
View File
@@ -0,0 +1,6 @@
steps:
- task: CacheBeta@0
inputs:
key: composer-v2 | composer.lock
path: $(COMPOSER_HOME)/cache
displayName: Cache composer packages
+11
View File
@@ -0,0 +1,11 @@
steps:
- task: CacheBeta@0
inputs:
key: sonarscanner-v1 | "$(SONAR_VERSION)" | scripts/tests/runsonar.sh
path: $(HOME)/sonarscanner
displayName: Cache sonar scanner
- task: CacheBeta@0
inputs:
key: sonarcache-v1 | "$(SONAR_VERSION)" | scripts/tests/runsonar.sh
path: $(HOME)/.sonar
displayName: Cache sonar cache
+6
View File
@@ -0,0 +1,6 @@
steps:
- task: CacheBeta@0
inputs:
key: yarn-v1 | yarn.lock
path: $(YARN_CACHE_FOLDER)
displayName: Cache Yarn packages
+1 -7
View File
@@ -2,13 +2,7 @@ parameters:
no_dev: 'false'
steps:
- task: Cache@2
inputs:
key: 'composer-v2 | composer.lock'
restoreKeys: |
composer-v2
path: $(COMPOSER_HOME)/cache
displayName: Cache composer packages
- template: step-cache-composer.yml
- script: composer validate
displayName: Validate composer files
+1 -14
View File
@@ -1,18 +1,5 @@
steps:
- task: Cache@2
inputs:
key: 'sonarscanner-v1 | "$(SONAR_VERSION)" | scripts/tests/runsonar.sh'
restoreKeys: |
sonarscanner-v1 | "$(SONAR_VERSION)"
path: $(HOME)/sonarscanner
displayName: Cache sonar scanner
- task: Cache@2
inputs:
key: 'sonarcache-v1 | "$(SONAR_VERSION)" | scripts/tests/runsonar.sh'
restoreKeys: |
sonarcache-v1 | "$(SONAR_VERSION)"
path: $(HOME)/.sonar
displayName: Cache sonar cache
- template: step-cache-sonar.yml
- bash: |
source scripts/ci/fixsecrets.sh
-5
View File
@@ -17,8 +17,3 @@ steps:
displayName: Run browser tests
env:
CHROME_DRIVER_OPTS: --headless --disable-gpu --disable-dev-shm-usage --no-sandbox --remote-debugging-port=9222
- bash: |
vendor/bin/phpcov merge --clover=results/coverage0.xml results/coverage/
rm -rf results/coverage
displayName: Fix coverage
+3 -1
View File
@@ -1,7 +1,8 @@
module.exports = {
"env": {
"browser": true,
"es6": true
"es6": true,
"cypress/globals": true
},
"extends": [
"plugin:vue/recommended"
@@ -12,6 +13,7 @@ module.exports = {
},
"plugins": [
"vue",
"cypress"
],
"rules": {
"array-bracket-spacing": [
+106
View File
@@ -0,0 +1,106 @@
name: Chrome headless
on: [push]
jobs:
cypress-run:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest]
php-version: ['7.3']
containers: [1, 2, 3, 4, 5, 6, 7, 8]
max-parallel: 10
steps:
- uses: actions/checkout@v1
- name: Setup PHP ${{ matrix.php-version }}
uses: shivammathur/setup-php@master
with:
php-version: ${{ matrix.php-version }}
coverage: none
- name: Check PHP Version
run: php -v
- name: Check Composer Version
run: composer -V
- name: Check PHP Extensions
run: php -m
# step-prepare-environment
- name: Prepare environment
run: |
mkdir -p results/coverage
sed 's/DB_TEST_PASSWORD=/DB_TEST_PASSWORD=root/' scripts/ci/.env.mysql > .env
touch .sentry-release
- run: echo "REQUIRES_SUBSCRIPTION=true" >> .env
- name: Validate composer.json and composer.lock
run: composer validate
- name: Get Composer Cache Directory
id: composer-cache-dir-path
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer files
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-interaction --no-suggest --ignore-platform-reqs
# step-prepare-db
- name: Start Mysql
run: sudo service mysql start
- name: Create db
run: mysql --protocol=tcp -u root -proot -e "CREATE DATABASE IF NOT EXISTS monica CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
- name: Prepare db
run: mysql -u root -proot monica < scripts/database.test.sql
- name: Run migration scripts
run: php artisan migrate --no-interaction -vvv
# step-seed-test-db
- name: Seed database
run: |
php artisan db:seed --no-interaction -vvv
php artisan passport:keys --no-interaction -vvv
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: yarn install
run: yarn inst
- name: Cypress verify
run: npm run cy:verify
- uses: cypress-io/github-action@v1
with:
start: php artisan serve
browser: chrome
headless: true
record: true
parallel: true
group: Azure DevOps CI
config: baseUrl=http://localhost:8000
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# - name: Store results
# uses: actions/upload-artifact@v1
# with:
# name: results
# path: results/junit/cypress/results*.xml
+2 -2
View File
@@ -14,8 +14,8 @@ npm-debug.log*
/results
.deploy.json
yarn-error.log
/tests/Cypress/screenshots
/tests/Cypress/videos
/tests/cypress/screenshots
/tests/cypress/videos
php-extensions-*.tar.bz2
monicadump.sql
.scannerwork/
@@ -1,80 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Helpers\DBHelper;
use App\Models\Account\Account;
use Illuminate\Console\Command;
use App\Console\Commands\Helpers\CommandExecutor;
use App\Console\Commands\Helpers\CommandExecutorInterface;
class SetupFrontEndTest extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'setup:frontendtesting';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create the test environment exclusively for front-end testing with Cypress.';
private $dumpfile = 'monicadump.sql';
private $account;
/**
* The Command Executor.
*
* @var CommandExecutorInterface
*/
public $commandExecutor;
/**
* Create a new command.
*/
public function __construct()
{
$this->commandExecutor = new CommandExecutor($this);
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$connection = DBHelper::connection();
if (file_exists('monicadump.sql')) {
$cmd = 'mysql -u '.$connection->getConfig('username');
if ($connection->getConfig('password') != '') {
$cmd .= ' -p'.$connection->getConfig('password');
}
if ($connection->getConfig('host') != '') {
$cmd .= ' -h '.$connection->getConfig('host');
}
if ($connection->getConfig('port') != '') {
$cmd .= ' -P '.$connection->getConfig('port');
}
$cmd .= ' '.$connection->getDatabaseName();
$cmd .= ' < '.$this->dumpfile;
$this->commandExecutor->exec('mysql import ...', $cmd);
} else {
$this->commandExecutor->artisan('perform fresh migration', 'migrate:fresh');
}
$this->info('Create account');
$this->account = Account::createDefault('John', 'Doe', 'admin@admin.com', 'admin0');
// get first user
$this->info('Fix first user');
$user = $this->account->users()->first();
$user->markEmailAsVerified();
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Console\Commands\Tests;
use App\Models\User\User;
use Illuminate\Console\Command;
use App\Services\User\AcceptPolicy;
class SetupFrontEndTestUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'setup:frontendtestuser {--database= : The database connection to use}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a user exclusively for front-end testing with Cypress.';
/**
* The migrator instance.
*
* @var \Illuminate\Database\Migrations\Migrator
*/
protected $migrator;
/**
* Create a new command.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->migrator = app('migrator');
}
/**
* Execute the console command.
*
* @return void
*/
public function handle(): void
{
$this->migrator->setConnection($this->option('database'));
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account->id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->info($user->getKey());
}
}
+13 -2
View File
@@ -20,11 +20,11 @@ use App\Console\Commands\SetupProduction;
use App\Console\Commands\UpdateGravatars;
use App\Console\Commands\PingVersionServer;
use App\Console\Commands\SetPremiumAccount;
use App\Console\Commands\SetupFrontEndTest;
use Illuminate\Console\Scheduling\Schedule;
use App\Console\Commands\CalculateStatistics;
use App\Console\Commands\OneTime\MoveAvatars;
use App\Console\Commands\MigrateDatabaseCollation;
use App\Console\Commands\Tests\SetupFrontEndTestUser;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Console\Commands\OneTime\MoveAvatarsToPhotosDirectory;
@@ -52,7 +52,6 @@ class Kernel extends ConsoleKernel
SendStayInTouch::class,
SentryRelease::class,
SetPremiumAccount::class,
SetupFrontEndTest::class,
SetupProduction::class,
SetupTest::class,
SetUserAdmin::class,
@@ -60,6 +59,18 @@ class Kernel extends ConsoleKernel
UpdateGravatars::class,
];
/**
* Register the Closure based commands for the application.
*
* @return void
*/
protected function commands()
{
if ($this->app->environment() != 'production') {
$this->commands[] = SetupFrontEndTestUser::class;
}
}
/**
* Define the application's command schedule.
*
+2 -2
View File
@@ -223,7 +223,7 @@ class SettingsController
*/
public function upload()
{
if (config('monica.requires_subscription') && ! auth()->user()->account->isSubscribed()) {
if (AccountHelper::hasLimitations(auth()->user()->account)) {
return redirect()->route('settings.subscriptions.index');
}
@@ -284,7 +284,7 @@ class SettingsController
*/
public function addUser()
{
if (config('monica.requires_subscription') && ! auth()->user()->account->isSubscribed()) {
if (AccountHelper::hasLimitations(auth()->user()->account)) {
return redirect()->route('settings.subscriptions.index');
}
Regular → Executable
View File
-1
View File
@@ -34,7 +34,6 @@ stages:
- template: .azure/job-reporting.yml
- template: .azure/job-test-migrations.yml
- stage: deploy
displayName: 'Deploy'
dependsOn: build
+6 -1
View File
@@ -7,5 +7,10 @@
"integrationFolder": "tests/cypress/integration",
"pluginsFile": "tests/cypress/plugins/index.js",
"video": false,
"projectId": "2i96ir"
"reporter": "junit",
"reporterOptions": {
"mochaFile": "results/junit/cypress/results-[hash].xml",
"toConsole": true
},
"projectId": "q8h6k9"
}
+16 -4
View File
@@ -8,23 +8,35 @@
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "yarn run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"e2e": "$(yarn bin)/cypress run",
"e2e-gui": "$(yarn bin)/cypress open",
"e2e": "cypress run",
"e2e:chrome": "cypress run --browser chrome",
"e2e:record": "cypress run --record",
"e2e:record:parallel": "cypress run --record --parallel",
"e2e-gui": "cypress open",
"cy:verify": "cypress verify",
"cy:version": "cypress version",
"inst": "yarn install --ignore-engines --frozen-lockfile",
"lint": "eslint --ext .js,.vue resources/js/",
"lint:cypress": "eslint --ext .js tests/cypress/",
"lint:all": "yarn lint & yarn lint:cypress",
"lint:fix": "yarn lint --fix & yarn lint:cypress --fix",
"snyk-protect": "snyk protect",
"prepublish": "yarn run snyk-protect"
"prepublish": "npm run snyk-protect",
"delete:reports": "rm results/cypress/* || true",
"pree2e": "npm run delete:reports"
},
"devDependencies": {
"cross-env": "^7.0.2",
"cypress": "4.1.0",
"cypress": "4.2.0",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.0.0",
"eslint-plugin-cypress": "^2.7.0",
"eslint-plugin-import": ">=2.20.1",
"eslint-plugin-node": ">=11.0.0",
"eslint-plugin-promise": ">=4.0.0",
"eslint-plugin-standard": ">=4.0.0",
"eslint-plugin-vue": "^6.2.2",
"faker": "^4.1.0",
"mocha": "^7.1.1",
"mocha-junit-reporter": "^1.23.3",
"mocha-multi-reporters": "^1.1.7",
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,7 +1,7 @@
{
"/js/manifest.js": "/js/manifest.js?id=7db827d654313dce4250",
"/js/vendor.js": "/js/vendor.js?id=72f839dc69acbe978c03",
"/js/app.js": "/js/app.js?id=830f09a5ccad06953c64",
"/js/app.js": "/js/app.js?id=bf31ffd8189f0d54e3cb",
"/css/app-ltr.css": "/css/app-ltr.css?id=065d5524629b65ed5c99",
"/css/app-rtl.css": "/css/app-rtl.css?id=0edb3575fdc79feb7ec2",
"/css/stripe.css": "/css/stripe.css?id=76c70a7b11ae5f38a725",
+2
View File
@@ -303,6 +303,8 @@ Vue.component(
require('./components/settings/DAVResources.vue').default
);
require('./testing');
var common = require('./common').default;
common.loadLanguage(window.Laravel.locale, true).then((i18n) => {
@@ -13,12 +13,14 @@
<journal-rate-day @hasRated="hasRated" />
<!-- Logs -->
<div v-for="journalEntry in journalEntries.data" :key="journalEntry.id" class="cf" :cy-name="'entry-body-' + journalEntry.id">
<journal-content-rate v-if="journalEntry.journalable_type == 'App\\Models\\Journal\\Day'" :journal-entry="journalEntry" @deleteJournalEntry="deleteJournalEntry" />
<div v-if="journalEntries.data" v-cy-name="'journal-entries-body'" v-cy-items="journalEntries.data.map(j => j.id)" :cy-object-items="journalEntries.data.map(j => j.object.id)">
<div v-for="journalEntry in journalEntries.data" :key="journalEntry.id" v-cy-name="'entry-body-' + journalEntry.id" class="cf">
<journal-content-rate v-if="journalEntry.journalable_type == 'App\\Models\\Journal\\Day'" :journal-entry="journalEntry" @deleteJournalEntry="deleteJournalEntry" />
<journal-content-activity v-else-if="journalEntry.journalable_type == 'App\\Models\\Account\\Activity'" :journal-entry="journalEntry" />
<journal-content-activity v-else-if="journalEntry.journalable_type == 'App\\Models\\Account\\Activity'" :journal-entry="journalEntry" />
<journal-content-entry v-else-if="journalEntry.journalable_type == 'App\\Models\\Journal\\Entry'" :journal-entry="journalEntry" @deleteJournalEntry="deleteJournalEntry" />
<journal-content-entry v-else-if="journalEntry.journalable_type == 'App\\Models\\Journal\\Entry'" :journal-entry="journalEntry" @deleteJournalEntry="deleteJournalEntry" />
</div>
</div>
<div v-if="(journalEntries.per_page * journalEntries.current_page) <= journalEntries.total" class="br3 ba b--gray-monica bg-white pr3 pb3 pt3 mb3 tc">
@@ -32,7 +34,7 @@
</p>
</div>
<div v-if="journalEntries.total === 0" class="br3 ba b--gray-monica bg-white pr3 pb3 pt3 mb3 tc" cy-name="journal-blank-state">
<div v-if="journalEntries.total === 0" v-cy-name="'journal-blank-state'" class="br3 ba b--gray-monica bg-white pr3 pb3 pt3 mb3 tc">
<div class="tc mb4">
<img src="img/journal/blank.svg" :alt="$t('journal.journal_empty')" />
</div>
@@ -45,7 +47,7 @@
<!-- Right sidebar -->
<div :class="[ dirltr ? 'fl' : 'fr' ]" class="w-30 pa2">
<a href="journal/add" class="btn btn-primary w-100 mb4" cy-name="add-entry-button">
<a v-cy-name="'add-entry-button'" href="journal/add" class="btn btn-primary w-100 mb4">
{{ $t('journal.journal_add') }}
</a>
<p>{{ $t('journal.journal_description') }}</p>
+21 -16
View File
@@ -24,9 +24,10 @@
<div class="flex items-center h-100">
<div class="flex-none w-100" :class="[ dirltr ? 'tr' : 'tl' ]">
<!-- sad smiley monochrome -->
<svg v-if="!showSadSmileyColor" width="42px" height="41px" viewBox="0 0 42 41" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="pointer" :class="{ selected: day.rate == 1 }" @click="showComment(1)"
@mouseover="showSadSmileyColor = true"
<svg v-if="!showSadSmileyColor" v-cy-name="'sad-reaction-button'" width="42px" height="41px" viewBox="0 0 42 41"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
class="pointer" :class="{ selected: day.rate == 1 }"
@click="showComment(1)" @mouseover="showSadSmileyColor = true"
>
<defs />
<g id="App" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
@@ -43,9 +44,10 @@
</svg>
<!-- sad smiley color -->
<svg v-if="showSadSmileyColor" width="42px" height="41px" viewBox="0 0 42 41" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="pointer" :class="{ selected: day.rate == 1 }" @click="showComment(1)"
@mouseleave="showSadSmileyColor = false"
<svg v-if="showSadSmileyColor" v-cy-name="'sad-reaction-button'" width="42px" height="41px" viewBox="0 0 42 41"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
class="pointer" :class="{ selected: day.rate == 1 }"
@click="showComment(1)" @mouseleave="showSadSmileyColor = false"
>
<defs />
<g id="App" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
@@ -62,8 +64,9 @@
</svg>
<!-- mediocre day monochrome -->
<svg width="42px" height="41px" viewBox="0 0 42 41" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" class="pointer" :class="{ selected: day.rate == 2 }" @click="showComment(2)"
<svg v-cy-name="'medium-reaction-button'" width="42px" height="41px" viewBox="0 0 42 41" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
class="pointer" :class="{ selected: day.rate == 2 }" @click="showComment(2)"
>
<defs />
<g id="App" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
@@ -79,9 +82,10 @@
</svg>
<!-- happy day monochrome -->
<svg v-if="!showHappySmileyColor" width="42px" height="42px" viewBox="0 0 42 42" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="pointer" :class="{ selected: day.rate == 3 }" @click="showComment(3)"
@mouseover="showHappySmileyColor = true"
<svg v-if="!showHappySmileyColor" v-cy-name="'happy-reaction-button'" width="42px" height="42px" viewBox="0 0 42 42"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
class="pointer" :class="{ selected: day.rate == 3 }"
@click="showComment(3)" @mouseover="showHappySmileyColor = true"
>
<defs />
<g id="App" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
@@ -99,9 +103,10 @@
</svg>
<!-- happy day color -->
<svg v-if="showHappySmileyColor" width="42px" height="42px" viewBox="0 0 42 42" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="pointer" :class="{ selected: day.rate == 3 }" @click="showComment(3)"
@mouseleave="showHappySmileyColor = false"
<svg v-if="showHappySmileyColor" v-cy-name="'happy-reaction-button'" width="42px" height="42px" viewBox="0 0 42 42"
version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
class="pointer" :class="{ selected: day.rate == 3 }"
@click="showComment(3)" @mouseleave="showHappySmileyColor = false"
>
<defs />
<g id="App" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
@@ -123,7 +128,7 @@
</div>
<!-- COMMENT BOX -->
<div v-if="hasRated == 'addComment'" :key="'comment'" class="pt2">
<div v-if="hasRated == 'addComment'" :key="'comment'" v-cy-name="'comment'" class="pt2">
<form-textarea
:id="'comment'"
v-model="day.comment"
@@ -140,7 +145,7 @@
</a>
</div>
<div>
<button class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click="rate()">
<button v-cy-name="'save-entry-button'" class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click="rate()">
{{ $t('app.save') }}
</button>
</div>
@@ -35,12 +35,12 @@
<ul class="f7">
<li class="di">
<a class="pointer" :cy-name="'entry-edit-button-' + entry.id" :href="'journal/entries/' + entry.id + '/edit'">
<a v-cy-name="'entry-edit-button-' + entry.id" class="pointer" :href="'journal/entries/' + entry.id + '/edit'">
{{ $t('app.edit') }}
</a>
</li>
<li class="di">
<a class="pointer" :cy-name="'entry-delete-button-' + entry.id" href="" @click.prevent="trash()">
<a v-cy-name="'entry-delete-button-' + entry.id" class="pointer" href="" @click.prevent="trash()">
{{ $t('app.delete') }}
</a>
</li>
@@ -99,7 +99,7 @@
{{ $t('journal.journal_entry_rate') }}
</li>
<li class="di">
<a class="pointer" :cy-name="'entry-delete-button-' + journalEntry.id" href="" @click.prevent="destroy()">
<a v-cy-name="'entry-delete-button-' + journalEntry.id" class="pointer" href="" @click.prevent="destroy()">
{{ $t('app.delete') }}
</a>
</li>
+5 -1
View File
@@ -17,7 +17,7 @@
<a class="btn mt2" href="" @click.prevent="close">
{{ $t('app.cancel') }}
</a>
<button class="btn btn-primary w-auto-ns w100 mt2 pb0-ns" @click="confirm($event)">
<button v-cy-name="'confirm-' + name" class="btn btn-primary w-auto-ns w100 mt2 pb0-ns" @click="confirm($event)">
{{ $t('app.confirm') }}
</button>
</div>
@@ -35,6 +35,10 @@ export default {
},
props: {
name: {
type: String,
default: '',
},
title: {
type: String,
default: '',
+12 -11
View File
@@ -11,22 +11,22 @@
<div>
<div>
<form class="bg-near-white pa2 br2 mb3">
<textarea v-model="newNote.body" class="w-100 br2 pa2 b--light-gray" cy-name="add-note-textarea" :placeholder="$t('people.notes_add_cta')" @focus="addMode = true"
<textarea v-model="newNote.body" v-cy-name="'add-note-textarea'" class="w-100 br2 pa2 b--light-gray" :placeholder="$t('people.notes_add_cta')" @focus="addMode = true"
@keyup.esc="addMode = false"
></textarea>
<a v-if="addMode" class="pointer btn btn-primary" cy-name="add-note-button" href="" @click.prevent="store">
<a v-if="addMode" v-cy-name="'add-note-button'" class="pointer btn btn-primary" href="" @click.prevent="store">
{{ $t('app.add') }}
</a>
<a v-if="addMode" class="pointer btn btn-secondary" cy-name="cancel-note-button" href="" @click.prevent="addMode = false">
<a v-if="addMode" v-cy-name="'cancel-note-button'" class="pointer btn btn-secondary" href="" @click.prevent="addMode = false">
{{ $t('app.cancel') }}
</a>
</form>
</div>
<!-- LIST OF NORMAL NOTES -->
<ul>
<ul v-cy-name="'notes-body'" v-cy-items="notes.map(n => n.id)">
<li v-for="note in notes" :key="note.id" class="note">
<div v-show="!note.edit" class="ba br2 b--black-10 br--top w-100 mb2" :cy-name="'note-body-' + note.id">
<div v-show="!note.edit" v-cy-name="'note-body-' + note.id" class="ba br2 b--black-10 br--top w-100 mb2">
<div class="pa2 markdown">
<span dir="auto" v-html="note.parsed_body"></span>
</div>
@@ -38,11 +38,11 @@
{{ note.created_at_short }}
</div>
<div class="fl w-50 tr">
<a class="pointer" :cy-name="'edit-note-button-' + note.id" href="" @click.prevent="toggleEditMode(note)">
<a v-cy-name="'edit-note-button-' + note.id" class="pointer" href="" @click.prevent="toggleEditMode(note)">
{{ $t('app.edit') }}
</a>
|
<a class="pointer" :cy-name="'delete-note-button-' + note.id" href="" @click.prevent="showDelete(note)">
<a v-cy-name="'delete-note-button-' + note.id" class="pointer" href="" @click.prevent="showDelete(note)">
{{ $t('app.delete') }}
</a>
</div>
@@ -51,8 +51,8 @@
<!-- EDIT MODE -->
<form v-show="note.edit" class="bg-near-white pa2 br2 mt3 mb3">
<textarea v-model="note.body" class="w-100 br2 pa2 b--light-gray" :cy-name="'edit-note-body-' + note.id" @keyup.esc="note.edit = false"></textarea>
<a class="pointer btn btn-primary" :cy-name="'edit-mode-note-button-' + note.id" href="" @click.prevent="update(note)">
<textarea v-model="note.body" v-cy-name="'edit-note-body-' + note.id" class="w-100 br2 pa2 b--light-gray" @keyup.esc="note.edit = false"></textarea>
<a v-cy-name="'edit-mode-note-button-' + note.id" class="pointer btn btn-primary" href="" @click.prevent="update(note)">
{{ $t('app.update') }}
</a>
</form>
@@ -61,7 +61,8 @@
</div>
<!-- Delete Note modal -->
<sweet-modal ref="modalDeleteNote" overlay-theme="dark"
<sweet-modal ref="modalDeleteNote" v-cy-name="'modal-delete-note'"
overlay-theme="dark"
:title="$t('people.notes_delete_title')"
>
<p>
@@ -71,7 +72,7 @@
<a class="btn" href="" @click.prevent="closeModal">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" :cy-name="'delete-mode-note-button-' + deleteNote.id"
<a v-cy-name="'delete-mode-note-button-' + deleteNote.id" class="btn btn-primary" href=""
@click.prevent="trash(deleteNote)"
>
{{ $t('app.delete') }}
@@ -5,13 +5,13 @@
<div class="di f5 normal">
<notifications group="favorite" position="top middle" width="400" />
<svg v-if="!isFavorite" v-tooltip.top="$t('people.set_favorite')" :cy-name="'set-favorite'" class="pointer" width="23"
<svg v-if="!isFavorite" v-tooltip.top="$t('people.set_favorite')" v-cy-name="'set-favorite'" class="pointer" width="23"
height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg" @click="store(true)"
>
<path d="M14.6053 7.404L14.7224 7.68675L15.0275 7.7111C16.7206 7.84628 18.1486 7.92359 19.2895 7.98536C19.9026 8.01855 20.4327 8.04725 20.8765 8.07803C21.5288 8.12327 21.9886 8.17235 22.2913 8.24003C22.3371 8.25027 22.3765 8.26035 22.4102 8.27001C22.3896 8.29619 22.3651 8.32572 22.336 8.35877C22.1328 8.58945 21.7914 8.89714 21.2913 9.31475C20.9474 9.60184 20.5299 9.93955 20.0459 10.331C19.1625 11.0455 18.0577 11.9391 16.7762 13.0302L16.543 13.2288L16.614 13.5267C17.0045 15.1663 17.3689 16.5406 17.6601 17.6391C17.819 18.2381 17.956 18.7552 18.0638 19.1886C18.2209 19.8206 18.3149 20.2704 18.3428 20.5768C18.347 20.6222 18.3493 20.6616 18.3505 20.6957C18.3176 20.6838 18.2798 20.6688 18.2367 20.6502C17.9532 20.5277 17.5539 20.2981 17.0014 19.9522C16.6264 19.7175 16.1833 19.4306 15.671 19.099C14.7143 18.4797 13.5162 17.7042 12.0695 16.8199L11.8087 16.6604L11.5478 16.82C10.0753 17.7209 8.86032 18.5085 7.89223 19.136C7.3851 19.4648 6.94572 19.7496 6.57253 19.9838C6.01576 20.3332 5.61353 20.5656 5.32808 20.6899C5.28721 20.7077 5.25111 20.7222 5.21941 20.7339C5.22088 20.7009 5.22355 20.663 5.22783 20.6197C5.25839 20.3111 5.35605 19.8582 5.51781 19.2225C5.62627 18.7962 5.76269 18.2914 5.92018 17.7087C6.22053 16.5972 6.59748 15.2024 7.00309 13.5286L7.07553 13.2297L6.84141 13.0303C5.52399 11.9079 4.39683 10.9982 3.50024 10.2747C3.03915 9.90254 2.63904 9.57963 2.30539 9.30232C1.80195 8.88388 1.45729 8.57562 1.25116 8.34437C1.22315 8.31293 1.19929 8.28466 1.17903 8.25939C1.20999 8.25084 1.24557 8.24198 1.28628 8.233C1.58841 8.1663 2.048 8.11835 2.701 8.07418C3.1353 8.0448 3.65101 8.01744 4.24568 7.98589C5.39523 7.9249 6.83989 7.84824 8.56208 7.71111L8.86638 7.68688L8.98388 7.40514C9.61646 5.88824 10.1238 4.58366 10.5314 3.53571C10.7656 2.93365 10.9668 2.4163 11.1399 1.99205C11.3854 1.39027 11.5751 0.972355 11.7339 0.708729C11.7601 0.66516 11.7838 0.628777 11.8048 0.598565C11.8256 0.628571 11.849 0.664658 11.8748 0.707817C12.0327 0.971308 12.2212 1.38911 12.465 1.99089C12.6368 2.41509 12.8365 2.93242 13.0689 3.53445C13.4735 4.58244 13.9771 5.88709 14.6053 7.404Z" fill="#D9D8D8" fill-opacity="0.25" stroke="#C6C6C6" />
</svg>
<svg v-else class="pointer" :cy-name="'unset-favorite'" width="23" height="22"
<svg v-else v-cy-name="'unset-favorite'" class="pointer" width="23" height="22"
viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg" @click="store(false)"
>
<path d="M14.6053 7.404L14.7224 7.68675L15.0275 7.7111C16.7206 7.84628 18.1486 7.92359 19.2895 7.98536C19.9026 8.01855 20.4327 8.04725 20.8765 8.07803C21.5288 8.12327 21.9886 8.17235 22.2913 8.24003C22.3371 8.25027 22.3765 8.26035 22.4102 8.27001C22.3896 8.29619 22.3651 8.32572 22.336 8.35877C22.1328 8.58945 21.7914 8.89714 21.2913 9.31475C20.9474 9.60184 20.5299 9.93955 20.0459 10.331C19.1625 11.0455 18.0577 11.9391 16.7762 13.0302L16.543 13.2288L16.614 13.5267C17.0045 15.1663 17.3689 16.5406 17.6601 17.6391C17.819 18.2381 17.956 18.7552 18.0638 19.1886C18.2209 19.8206 18.3149 20.2704 18.3428 20.5768C18.347 20.6222 18.3493 20.6616 18.3505 20.6957C18.3176 20.6838 18.2798 20.6688 18.2367 20.6502C17.9532 20.5277 17.5539 20.2981 17.0014 19.9522C16.6264 19.7175 16.1833 19.4306 15.671 19.099C14.7143 18.4797 13.5162 17.7042 12.0695 16.8199L11.8087 16.6604L11.5478 16.82C10.0753 17.7209 8.86032 18.5085 7.89223 19.136C7.3851 19.4648 6.94572 19.7496 6.57253 19.9838C6.01576 20.3332 5.61353 20.5656 5.32808 20.6899C5.28721 20.7077 5.25111 20.7222 5.21941 20.7339C5.22088 20.7009 5.22355 20.663 5.22783 20.6197C5.25839 20.3111 5.35605 19.8582 5.51781 19.2225C5.62627 18.7962 5.76269 18.2914 5.92018 17.7087C6.22053 16.5972 6.59748 15.2024 7.00309 13.5286L7.07553 13.2297L6.84141 13.0303C5.52399 11.9079 4.39683 10.9982 3.50024 10.2747C3.03915 9.90254 2.63904 9.57963 2.30539 9.30232C1.80195 8.88388 1.45729 8.57562 1.25116 8.34437C1.22315 8.31293 1.19929 8.28466 1.17903 8.25939C1.20999 8.25084 1.24557 8.24198 1.28628 8.233C1.58841 8.1663 2.048 8.11835 2.701 8.07418C3.1353 8.0448 3.65101 8.01744 4.24568 7.98589C5.39523 7.9249 6.83989 7.84824 8.56208 7.71111L8.86638 7.68688L8.98388 7.40514C9.61646 5.88824 10.1238 4.58366 10.5314 3.53571C10.7656 2.93365 10.9668 2.4163 11.1399 1.99205C11.3854 1.39027 11.5751 0.972355 11.7339 0.708729C11.7601 0.66516 11.7838 0.628777 11.8048 0.598565C11.8256 0.628571 11.849 0.664658 11.8748 0.707817C12.0327 0.971308 12.2212 1.38911 12.465 1.99089C12.6368 2.41509 12.8365 2.93242 13.0689 3.53445C13.4735 4.58244 13.9771 5.88709 14.6053 7.404Z" fill="#F2C94C" stroke="#DCBB58" />
+11 -11
View File
@@ -9,10 +9,10 @@
{{ $t('people.section_personal_tasks') }}
<span v-if="tasks.length != 0" class="f6 pt2" :class="[ dirltr ? 'fr' : 'fl' ]">
<a v-if="!editMode" class="pointer" cy-name="task-toggle-edit-mode" href="" @click.prevent="editMode = true">
<a v-if="!editMode" v-cy-name="'task-toggle-edit-mode'" class="pointer" href="" @click.prevent="editMode = true">
{{ $t('app.edit') }}
</a>
<a v-else class="pointer" cy-name="task-toggle-edit-mode" href="" @click.prevent="editMode = false">
<a v-else v-cy-name="'task-toggle-edit-mode'" class="pointer" href="" @click.prevent="editMode = false">
{{ $t('app.done') }}
</a>
</span>
@@ -21,18 +21,18 @@
<div :class="[editMode ? 'bg-washed-yellow b--yellow ba pa2' : '']">
<!-- EMPTY STATE -->
<div v-if="tasks.length == 0 && !addMode" class="tc bg-near-white b--moon-gray pa3" cy-name="task-blank-state">
<div v-if="tasks.length == 0 && !addMode" v-cy-name="'task-blank-state'" class="tc bg-near-white b--moon-gray pa3">
<p>{{ $t('people.tasks_blank_title') }}</p>
<p>
<a class="pointer" cy-name="add-task-button" href="" @click.prevent="toggleAddMode">
<a v-cy-name="'add-task-button'" class="pointer" href="" @click.prevent="toggleAddMode">
{{ $t('people.tasks_add_task') }}
</a>
</p>
</div>
<!-- LIST OF IN PROGRESS TASKS -->
<ul>
<li v-for="(task, i) in inProgress(tasks)" :key="task.id" :cy-name="'task-item-' + task.id">
<ul v-cy-name="'tasks-body'" v-cy-items="inProgress(tasks).map(t => t.id)">
<li v-for="(task, i) in inProgress(tasks)" :key="task.id" v-cy-name="'task-item-' + task.id">
<form-checkbox
v-model.lazy="task.completed"
:disabled="task.disabled"
@@ -48,7 +48,7 @@
<div v-if="editMode" class="di">
<em class="fa fa-pencil-square-o pointer pr2 ml3 dark-blue" @click="toggleEditMode(task)"></em>
<em class="fa fa-trash-o pointer pr2 dark-blue" :cy-name="'task-delete-button-' + task.id" @click="trash(task)"></em>
<em v-cy-name="'task-delete-button-' + task.id" class="fa fa-trash-o pointer pr2 dark-blue" @click="trash(task)"></em>
</div>
<!-- EDIT BOX -->
@@ -91,13 +91,13 @@
</div>
<!-- ADD A TASK VIEW -->
<div v-if="addMode" cy-name="task-add-view">
<div v-if="addMode" v-cy-name="'task-add-view'">
<form class="bg-near-white pa2 br2 mt3 mb3">
<div>
<label for="add-title" class="db fw6 lh-copy f6">
{{ $t('people.tasks_form_title') }}
</label>
<input id="add-title" v-model="newTask.title" class="pa2 db w-100" type="text" cy-name="task-add-title"
<input id="add-title" v-model="newTask.title" v-cy-name="'task-add-title'" class="pa2 db w-100" type="text"
@keyup.esc="addMode = false"
/>
</div>
@@ -108,7 +108,7 @@
<textarea id="add-description" v-model="newTask.description" class="pa2 db w-100" type="text" @keyup.esc="addMode = false"></textarea>
</div>
<div class="lh-copy mt3">
<a class="btn btn-primary" cy-name="save-task-button" href="" @click.prevent="store">
<a v-cy-name="'save-task-button'" class="btn btn-primary" href="" @click.prevent="store">
{{ $t('app.add') }}
</a>
<a class="btn" href="" @click.prevent="addMode = false">
@@ -120,7 +120,7 @@
<!-- LIST OF COMPLETED TASKS -->
<ul>
<li v-for="task in completed(tasks)" :key="task.id" class="f6" :cy-name="'task-item-completed-' + task.id">
<li v-for="task in completed(tasks)" :key="task.id" v-cy-name="'task-item-completed-' + task.id" class="f6">
<form-checkbox
v-model.lazy="task.completed"
:disabled="task.disabled"
@@ -11,7 +11,7 @@
🍿 {{ $t('people.activity_title') }}
<span class="fr relative btn-title">
<a v-if="displayLogActivity == false" class="btn edit-information" @click="displayLogActivity = true">
<a v-if="displayLogActivity == false" v-cy-name="'add-activity-button'" class="btn edit-information" @click="displayLogActivity = true">
{{ $t('people.activities_add_activity') }}
</a>
<a v-else class="btn edit-information" @click="displayLogActivity = false">
@@ -23,7 +23,7 @@
<!-- BLANK STATE -->
<div v-if="!displayLogActivity && activities.length == 0" class="w-100">
<div class="bg-near-white tc pa3 br2 ba b--light-gray">
<div v-cy-name="'activities-blank-state'" class="bg-near-white tc pa3 br2 ba b--light-gray">
<p>{{ $t('people.activities_blank_title', { name: name }) }}</p>
<a class="pointer" href="" @click.prevent="displayLogActivity = true">
{{ $t('people.activities_blank_add_activity') }}
@@ -43,87 +43,89 @@
</template>
<!-- LIST OF ACTIVITIES -->
<div v-for="activity in activities" :key="activity.id" class="ba br2 b--black-10 br--top w-100 mb2">
<template v-if="!activity.edit">
<h2 class="pl2 pr2 pt3 f5">
{{ activity.summary }}
</h2>
<div v-cy-name="'activities-body'" v-cy-items="activities.map(c => c.id)">
<div v-for="activity in activities" :key="activity.id" v-cy-name="'activity-body-'+activity.id" class="ba br2 b--black-10 br--top w-100 mb2">
<template v-if="!activity.edit">
<h2 class="pl2 pr2 pt3 f5">
{{ activity.summary }}
</h2>
<div v-if="activity.description" dir="auto" class="markdown pl2 pr2 pb3" v-html="compiledMarkdown(activity.description)">
</div>
<!-- DETAILS -->
<div class="pa2 cf bt b--black-10 br--bottom f7">
<div class="w-70" :class="[ dirltr ? 'fl' : 'fr' ]">
<ul class="list">
<!-- HAPPENED AT -->
<li class="di" :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ activity.happened_at | moment }}
</li>
<!-- PARTICIPANT LIST -->
<li v-if="activity.attendees.total > 1" class="di">
<ul class="di list" :class="[ dirltr ? 'mr3' : 'ml3' ]">
<li class="di">
{{ $t('people.activities_list_participants') }}
</li>
<li v-for="attendee in activity.attendees.contacts.filter(c => c.id !== contactId)" :key="attendee.id" class="di mr2">
<a :href="'people/' + attendee.hash_id">{{ attendee.complete_name }}</a>
</li>
</ul>
</li>
<!-- EMOTIONS LIST -->
<li v-if="activity.emotions.length != 0" class="di">
<ul class="di list" :class="[ dirltr ? 'mr3' : 'ml3' ]">
<li class="di">
{{ $t('people.activities_list_emotions') }}
</li>
<li v-for="emotion in activity.emotions" :key="emotion.id" class="di">
{{ $t('app.emotion_' + emotion.name) }}
</li>
</ul>
</li>
<!-- ACTIVITY TYPE -->
<li v-if="activity.activity_type" class="di" :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ activity.activity_type.name }}
</li>
</ul>
<div v-if="activity.description" dir="auto" class="markdown pl2 pr2 pb3" v-html="compiledMarkdown(activity.description)">
</div>
<div class="w-30" :class="[ dirltr ? 'fl tr' : 'fr tl' ]">
<!-- ACTIONS -->
<ul class="list">
<li class="di">
<a href="" class="pointer" @click.prevent="$set(activity, 'edit', true)">{{ $t('app.edit') }}</a>
<a v-show="destroyActivityId != activity.id" href="" class="pointer" @click.prevent="showDestroyActivity(activity)">{{ $t('app.delete') }}</a>
<ul v-show="destroyActivityId == activity.id" class="di">
<li class="di">
<a class="pointer red" @click.prevent="destroyActivity(activity)">
{{ $t('app.delete_confirm') }}
</a>
</li>
<li class="di">
<a class="pointer mr1" @click.prevent="destroyActivityId = 0">
{{ $t('app.cancel') }}
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</template>
<!-- EDIT THE CURRENT ACTIVITY -->
<create-activity v-else
:hash="hash"
:name="name"
:activity="activity"
:contact-id="contactId"
@update="updateList($event)"
@cancel="$set(activity, 'edit', false); displayLogActivity = false"
/>
<!-- DETAILS -->
<div class="pa2 cf bt b--black-10 br--bottom f7">
<div class="w-70" :class="[ dirltr ? 'fl' : 'fr' ]">
<ul class="list">
<!-- HAPPENED AT -->
<li class="di" :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ activity.happened_at | moment }}
</li>
<!-- PARTICIPANT LIST -->
<li v-if="activity.attendees.total > 1" class="di">
<ul class="di list" :class="[ dirltr ? 'mr3' : 'ml3' ]">
<li class="di">
{{ $t('people.activities_list_participants') }}
</li>
<li v-for="attendee in activity.attendees.contacts.filter(c => c.id !== contactId)" :key="attendee.id" class="di mr2">
<a :href="'people/' + attendee.hash_id">{{ attendee.complete_name }}</a>
</li>
</ul>
</li>
<!-- EMOTIONS LIST -->
<li v-if="activity.emotions.length != 0" class="di">
<ul class="di list" :class="[ dirltr ? 'mr3' : 'ml3' ]">
<li class="di">
{{ $t('people.activities_list_emotions') }}
</li>
<li v-for="emotion in activity.emotions" :key="emotion.id" class="di">
{{ $t('app.emotion_' + emotion.name) }}
</li>
</ul>
</li>
<!-- ACTIVITY TYPE -->
<li v-if="activity.activity_type" class="di" :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ activity.activity_type.name }}
</li>
</ul>
</div>
<div class="w-30" :class="[ dirltr ? 'fl tr' : 'fr tl' ]">
<!-- ACTIONS -->
<ul class="list">
<li class="di">
<a v-cy-name="'edit-activity-button-'+activity.id" href="" class="pointer" @click.prevent="$set(activity, 'edit', true)">{{ $t('app.edit') }}</a>
<a v-show="destroyActivityId != activity.id" v-cy-name="'delete-activity-button-'+activity.id" href="" class="pointer" @click.prevent="showDestroyActivity(activity)">{{ $t('app.delete') }}</a>
<ul v-show="destroyActivityId == activity.id" class="di">
<li class="di">
<a v-cy-name="'confirm-delete-activity'" class="pointer red" @click.prevent="destroyActivity(activity)">
{{ $t('app.delete_confirm') }}
</a>
</li>
<li class="di">
<a class="pointer mr1" @click.prevent="destroyActivityId = 0">
{{ $t('app.cancel') }}
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</template>
<!-- EDIT THE CURRENT ACTIVITY -->
<create-activity v-else
:hash="hash"
:name="name"
:activity="activity"
:contact-id="contactId"
@update="updateList($event)"
@cancel="$set(activity, 'edit', false); displayLogActivity = false"
/>
</div>
</div>
<p v-if="activities.length > 0" class="tc">
@@ -3,6 +3,7 @@
<template>
<form-select
:id="'activity-type-list'"
:title="title"
:options="activityCategories"
:iclass="'br2 f5 w-100 ba b--black-40 pa2 outline-0'"
@@ -47,7 +47,7 @@
<a href="" @click.prevent="displayEmotions = true">{{ $t('people.activities_add_emotions') }}</a>
</li>
<li v-show="!displayCategory" class="di pointer mr3">
<a href="" @click.prevent="displayCategory = true">{{ $t('people.activities_add_category') }}</a>
<a v-cy-name="'activities_add_category'" href="" @click.prevent="displayCategory = true">{{ $t('people.activities_add_category') }}</a>
</li>
<li v-show="!displayParticipants" class="di pointer">
<a href="" @click.prevent="displayParticipants = true">{{ $t('people.activities_add_participants_cta') }}</a>
@@ -116,7 +116,7 @@
</a>
</div>
<div class="">
<button class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="store()">
<button v-cy-name="'save-activity-button'" class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="store()">
{{ activity ? $t('app.save') : $t('app.add') }}
</button>
</div>
@@ -8,8 +8,8 @@
{{ $t('people.call_title') }}
<span class="fr relative" style="top: -7px;">
<a v-if="displayLogCall == false" class="btn edit-information" href="" @click.prevent="displayLogCall = true">
{{ $t('people.modal_call_title') }}
<a v-if="displayLogCall == false" v-cy-name="'add-call-button'" class="btn edit-information" href="" @click.prevent="displayLogCall = true">
{{ $t('people.call_button') }}
</a>
<a v-if="displayLogCall" class="btn edit-information" href="" @click.prevent="displayLogCall = false">
{{ $t('app.cancel') }}
@@ -19,18 +19,18 @@
</div>
<!-- BLANK STATE -->
<div v-if="!displayLogCall && calls.length == 0" class="w-100">
<div v-if="!displayLogCall && calls.length == 0" v-cy-name="'calls-blank-state'" class="w-100">
<div class="bg-near-white tc pa3 br2 ba b--light-gray">
<p>{{ $t('people.call_blank_title', { name: name }) }}</p>
<a class="pointer" href="" @click.prevent="displayLogCall = true">
{{ $t('people.modal_call_title') }}
{{ $t('people.call_button') }}
</a>
</div>
</div>
<!-- LOG A CALL -->
<transition name="fade">
<div v-if="displayLogCall" class="ba br3 mb3 pa3 b--black-40">
<div v-if="displayLogCall" v-cy-name="'log-call-form'" class="ba br3 mb3 pa3 b--black-40">
<div class="dt dt--fixed pb3 mb3 mb0-ns">
<!-- WHEN -->
<div class="dtc pr2">
@@ -111,7 +111,7 @@
</a>
</div>
<div class="">
<button class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="store()">
<button v-cy-name="'save-call-button'" class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="store()">
{{ $t('app.add') }}
</button>
</div>
@@ -121,23 +121,24 @@
</transition>
<!-- LIST OF CALLS -->
<div v-for="call in calls" :key="call.id" class="ba br2 b--black-10 br--top w-100 mb2">
<div v-show="editCallId != call.id" class="pa2">
<span v-if="!call.content">
{{ $t('people.call_blank_desc', { name: call.contact.first_name }) }}
</span>
<span v-if="call.content" dir="auto" class="markdown" v-html="compiledMarkdown(call.content)"></span>
</div>
<div v-cy-name="'calls-body'" v-cy-items="calls.map(c => c.id)">
<div v-for="call in calls" :key="call.id" v-cy-name="'call-body-'+call.id" class="ba br2 b--black-10 br--top w-100 mb2">
<div v-show="editCallId != call.id" class="pa2">
<span v-if="!call.content">
{{ $t('people.call_blank_desc', { name: call.contact.first_name }) }}
</span>
<span v-if="call.content" dir="auto" class="markdown" v-html="compiledMarkdown(call.content)"></span>
</div>
<!-- INLINE UPDATE DIV -->
<div v-show="editCallId == call.id" class="pa2">
<div>
<!-- INLINE UPDATE DIV -->
<div v-show="editCallId == call.id" class="pa2">
<div>
<form-textarea
v-model="editCall.content"
:label="$t('people.modal_call_comment')"
:rows="4"
iclass="br2 f5 w-100 ba b--black-40 pa2 outline-0"
@contentChange="updateEditCallContent($event)"
/>
<p class="f6">
{{ $t('app.markdown_description') }}
@@ -153,88 +154,103 @@
<input :id="'you' + call.id" v-model="editCall.contact_called" type="radio" class="mr1" :name="'contact_called' + call.id"
:value="false"
/>
<label :for="'you' + call.id" class="pointer">
{{ $t('people.call_you_called') }}
</label>
<p class="f6">
{{ $t('app.markdown_description') }}
</p>
</div>
<div class="di mr3">
<input :id="'contact' + call.id" v-model="editCall.contact_called" type="radio" class="mr1" :name="'contact_called' + call.id"
:value="true"
/>
<label :for="'contact' + call.id" class="pointer">
{{ $t('people.call_he_called', { name : name }) }}
<!-- WHO CALLED -->
<div class="pb3 mb3 mb0-ns">
<p class="mb2">
{{ $t('people.modal_call_who_called') }}
</p>
<div class="di mr3">
<input :id="'you' + call.id" v-model="editCall.contact_called" type="radio" class="mr1" :name="'contact_called' + call.id"
:value="false"
/>
<label :for="'you' + call.id" class="pointer">
{{ $t('people.call_you_called') }}
</label>
</div>
<div class="di mr3">
<input :id="'contact' + call.id" v-model="editCall.contact_called" type="radio" class="mr1" :name="'contact_called' + call.id"
:value="true"
/>
<label :for="'contact' + call.id" class="pointer">
{{ $t('people.call_he_called', { name : name }) }}
</label>
</div>
</div>
<!-- EMOTIONS -->
<div class="bb b--gray-monica pb3 mb3">
<label class="b">
{{ $t('people.modal_call_emotion') }}
</label>
<emotion class="pv2" :initial-emotions="call.emotions" @update="updateEmotionsList" />
</div>
<!-- ACTIONS -->
<div class="">
<div class="flex-ns justify-between">
<div class="">
<a class="btn btn-secondary tc w-auto-ns w-100 mb2 pb0-ns" href="" @click.prevent="editCallId = 0">
{{ $t('app.cancel') }}
</a>
</div>
<div class="">
<button class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="update()">
{{ $t('app.update') }}
</button>
</div>
</div>
</div>
</div>
</div>
<!-- EMOTIONS -->
<div class="bb b--gray-monica pb3 mb3">
<label class="b">
{{ $t('people.modal_call_emotion') }}
</label>
<emotion class="pv2" :initial-emotions="call.emotions" @update="updateEmotionsList" />
<!-- ADDITIONAL INFORMATION -->
<div class="pa2 cf bt b--black-10 br--bottom f7 lh-copy">
<div class="w-70" :class="[ dirltr ? 'fl' : 'fr' ]">
<span :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ call.called_at | moment }}
</span>
<span :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ call.contact_called ? $t('people.call_he_called', { name : name }) : $t('people.call_you_called') }}
</span>
<!-- EMOTION LIST -->
<span v-if="call.emotions.length != 0">
<span :class="[ dirltr ? 'mr2' : 'ml2' ]">
{{ $t('people.call_emotions') }}
</span>
<ul class="di">
<li v-for="emotion in call.emotions" :key="emotion.id" class="di">
{{ $t('app.emotion_' + emotion.name) }}
</li>
</ul>
</span>
</div>
<!-- ACTIONS -->
<div class="">
<div class="flex-ns justify-between">
<div class="">
<a class="btn btn-secondary tc w-auto-ns w-100 mb2 pb0-ns" href="" @click.prevent="editCallId = 0">
<div :class="[ dirltr ? 'fl tr' : 'fr tl' ]" class="w-30">
<a :class="[ dirltr ? 'mr2' : 'ml2' ]" class="pointer " href="" @click.prevent="showEditBox(call)">
{{ $t('app.update') }}
</a>
<a v-show="destroyCallId != call.id" v-cy-name="'delete-call-button-'+call.id" class="pointer" href="" @click.prevent="showDestroyCall(call)">
{{ $t('app.delete') }}
</a>
<ul v-show="destroyCallId == call.id" class="di">
<li class="di">
<a class="pointer mr1" href="" @click.prevent="destroyCallId = 0">
{{ $t('app.cancel') }}
</a>
</div>
<div class="">
<button class="btn btn-primary w-auto-ns w-100 mb2 pb0-ns" @click.prevent="update()">
{{ $t('app.update') }}
</button>
</div>
</div>
</div>
</div>
</div>
<!-- ADDITIONAL INFORMATION -->
<div class="pa2 cf bt b--black-10 br--bottom f7 lh-copy">
<div class="w-70" :class="[ dirltr ? 'fl' : 'fr' ]">
<span :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ call.called_at | moment }}
</span>
<span :class="[ dirltr ? 'mr3' : 'ml3' ]">
{{ call.contact_called ? $t('people.call_he_called', { name : name }) : $t('people.call_you_called') }}
</span>
<!-- EMOTION LIST -->
<span v-if="call.emotions.length != 0">
<span :class="[ dirltr ? 'mr2' : 'ml2' ]">
{{ $t('people.call_emotions') }}
</span>
<ul class="di">
<li v-for="emotion in call.emotions" :key="emotion.id" class="di">
{{ $t('app.emotion_' + emotion.name) }}
</li>
<li class="di">
<a v-cy-name="'delete-call-confirm-button-'+call.id" class="pointer red" href="" @click.prevent="destroyCall(call)">
{{ $t('app.delete_confirm') }}
</a>
</li>
</ul>
</span>
</div>
<div :class="[ dirltr ? 'fl tr' : 'fr tl' ]" class="w-30">
<a :class="[ dirltr ? 'mr2' : 'ml2' ]" class="pointer " href="" @click.prevent="showEditBox(call)">
{{ $t('app.update') }}
</a>
<a v-show="destroyCallId != call.id" class="pointer" href="" @click.prevent="showDestroyCall(call)">
{{ $t('app.delete') }}
</a>
<ul v-show="destroyCallId == call.id" class="di">
<li class="di">
<a class="pointer mr1" href="" @click.prevent="destroyCallId = 0">
{{ $t('app.cancel') }}
</a>
</li>
<li class="di">
<a class="pointer red" href="" @click.prevent="destroyCall(call)">
{{ $t('app.delete_confirm') }}
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
@@ -10,7 +10,7 @@
<img src="img/people/gifts.svg" :alt="$t('people.gifts_title')" class="icon-section icon-tasks" />
<h3>
{{ $t('people.gifts_title') }}
<a href="" cy-name="add-gift-button" class="btn f6 pt2" :class="[ dirltr ? 'fr' : 'fl' ]"
<a v-cy-name="'add-gift-button'" href="" class="btn f6 pt2" :class="[ dirltr ? 'fr' : 'fl' ]"
@click.prevent="displayCreateGift = true"
>
{{ $t('people.gifts_add_gift') }}
@@ -54,7 +54,7 @@
</li>
</ul>
<div v-for="gift in filteredGifts" :key="gift.id" class="ba b--gray-monica mb3 br2" :cy-name="'gift-item-' + gift.id">
<div v-for="gift in filteredGifts" :key="gift.id" v-cy-name="'gift-item-' + gift.id" class="ba b--gray-monica mb3 br2">
<gift v-if="!gift.edit"
:gift="gift"
@update="($event) => { updateList($event) }"
@@ -69,12 +69,12 @@
</div>
<div :class="dirltr ? 'fr' : 'fl'">
<a :class="dirltr ? 'mr1' : 'ml1'" class="di" href="" :cy-name="'edit-gift-button-' + gift.id"
<a v-cy-name="'edit-gift-button-' + gift.id" :class="dirltr ? 'mr1' : 'ml1'" class="di" href=""
@click.prevent="$set(gift, 'edit', true)"
>
{{ $t('app.edit') }}
</a>
<a :class="dirltr ? 'mr1' : 'ml1'" class="di" href="" :cy-name="'delete-gift-button-' + gift.id"
<a v-cy-name="'delete-gift-button-' + gift.id" :class="dirltr ? 'mr1' : 'ml1'" class="di" href=""
@click.prevent="showDeleteModal(gift)"
>
{{ $t('app.delete') }}
@@ -103,7 +103,7 @@
<a class="btn" href="" @click.prevent="closeDeleteModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" :cy-name="'modal-delete-gift-button-' + giftToTrash.id" href="" @click.prevent="trash(giftToTrash)">
<a v-cy-name="'modal-delete-gift-button-' + giftToTrash.id" class="btn btn-primary" href="" @click.prevent="trash(giftToTrash)">
{{ $t('app.delete') }}
</a>
</div>
@@ -536,7 +536,7 @@
<a class="btn center" href="" @click.prevent="closeDeleteModal()">
{{ $t('app.cancel') }}
</a>
<a :cy-name="'delete-life-event-button'" class="btn btn-primary" href="" @click.prevent="destroy(lifeEventToDelete)">
<a v-cy-name="'delete-life-event-button'" class="btn btn-primary" href="" @click.prevent="destroy(lifeEventToDelete)">
{{ $t('app.delete') }}
</a>
</div>
@@ -7,13 +7,15 @@
<h3 class="with-actions">
{{ $t('settings.personalization_activity_type_category_title') }}
<a v-if="!limited" class="btn nt2" :class="[ dirltr ? 'fr' : 'fl' ]" href="" @click.prevent="showCreateCategoryModal">
<a v-if="!limited" v-cy-name="'add-activity-type-category-button'" class="btn nt2" :class="[ dirltr ? 'fr' : 'fl' ]" href=""
@click.prevent="showCreateCategoryModal"
>
{{ $t('settings.personalization_activity_type_category_add') }}
</a>
</h3>
<p>{{ $t('settings.personalization_activity_type_category_description') }}</p>
<div v-if="limited" class="mt3 mb3 form-information-message br2">
<div v-if="limited" v-cy-name="'activity-type-premium-message'" class="mt3 mb3 form-information-message br2">
<div class="pa3 flex">
<div class="mr3">
<svg viewBox="0 0 20 20">
@@ -41,45 +43,59 @@
</div>
</div>
<div>
<div v-for="activityTypeCategory in activityTypeCategories" :key="activityTypeCategory.id" class="dt dt--fixed w-100 collapse br--top br--bottom mt3">
<!-- ACTIVITY TYPE CATEGORY -->
<div class="dt-row hover bb b--light-gray">
<div class="dtc">
<div class="pa2 b">
<strong>{{ activityTypeCategory.name }}</strong>
<div v-cy-name="'activity-types'">
<ul v-cy-name="'activity-type-categories'" v-cy-items="activityTypeCategories.map(a => a.id)">
<li v-for="activityTypeCategory in activityTypeCategories" :key="activityTypeCategory.id" v-cy-name="'activity-types-'+activityTypeCategory.id"
v-cy-items="activityTypeCategory.activityTypes ? activityTypeCategory.activityTypes.map(a => a.id) : ''" class="dt dt--fixed w-100 collapse br--top br--bottom mt3"
>
<!-- ACTIVITY TYPE CATEGORY -->
<div class="dt-row hover bb b--light-gray">
<div class="dtc">
<div class="pa2 b">
<strong>{{ activityTypeCategory.name }}</strong>
</div>
</div>
<div class="dtc">
<div class="pa2" :class="[ dirltr ? 'tr' : 'tl' ]">
<em v-if="!limited" v-cy-name="'activity-type-category-edit-button-'+activityTypeCategory.id"
class="fa fa-pencil-square-o pointer pr2" @click="showEditCategory(activityTypeCategory)"
></em>
<em v-if="!limited" v-cy-name="'activity-type-category-delete-button-'+activityTypeCategory.id"
class="fa fa-trash-o pointer" @click="showDeleteCategory(activityTypeCategory)"
></em>
</div>
</div>
</div>
<div class="dtc">
<div class="pa2" :class="[ dirltr ? 'tr' : 'tl' ]">
<em v-if="!limited" class="fa fa-pencil-square-o pointer pr2" @click="showEditCategory(activityTypeCategory)"></em>
<em v-if="!limited" class="fa fa-trash-o pointer" @click="showDeleteCategory(activityTypeCategory)"></em>
<div v-for="activityType in activityTypeCategory.activityTypes" :key="activityType.id" class="dt-row hover bb b--light-gray">
<div class="dtc">
<div class="pa2 pl4">
{{ activityType.name }}
</div>
</div>
<div class="dtc" :class="[ dirltr ? 'tr' : 'tl' ]">
<div class="pa2">
<em v-if="!limited" v-cy-name="'activity-type-edit-button-'+activityType.id"
class="fa fa-pencil-square-o pointer pr2" @click="showEditType(activityType, activityTypeCategory.id)"
></em>
<em v-if="!limited" v-cy-name="'activity-type-delete-button-'+activityType.id"
class="fa fa-trash-o pointer" @click="showDeleteType(activityType)"
></em>
</div>
</div>
</div>
</div>
<div v-for="activityType in activityTypeCategory.activityTypes" :key="activityType.id" class="dt-row hover bb b--light-gray">
<div class="dtc">
<div class="pa2 pl4">
{{ activityType.name }}
<div v-if="!limited" class="dt-row">
<div class="dtc">
<div class="pa2 pl4">
<a v-cy-name="'add-activity-type-button-for-category-'+activityTypeCategory.id" class="pointer" href=""
@click.prevent="showCreateTypeModal(activityTypeCategory)"
>
{{ $t('settings.personalization_activity_type_add_button') }}
</a>
</div>
</div>
</div>
<div class="dtc" :class="[ dirltr ? 'tr' : 'tl' ]">
<div class="pa2">
<em v-if="!limited" class="fa fa-pencil-square-o pointer pr2" @click="showEditType(activityType)"></em>
<em v-if="!limited" class="fa fa-trash-o pointer" @click="showDeleteType(activityType)"></em>
</div>
</div>
</div>
<div v-if="!limited" class="dt-row">
<div class="dtc">
<div class="pa2 pl4">
<a class="pointer" href="" @click.prevent="showCreateTypeModal(activityTypeCategory)">
{{ $t('settings.personalization_activity_type_add_button') }}
</a>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
<!-- Create Activity Type Category -->
@@ -100,7 +116,7 @@
<a class="btn" href="" @click.prevent="closeCategoryModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="storeCategory()">
<a v-cy-name="'add-activity-type-category-save-button'" class="btn btn-primary" href="" @click.prevent="storeCategory()">
{{ $t('app.save') }}
</a>
</div>
@@ -124,7 +140,7 @@
<a class="btn" href="" @click.prevent="closeUpdateCategoryModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="updateCategory()">
<a v-cy-name="'update-activity-type-category-button'" class="btn btn-primary" href="" @click.prevent="updateCategory()">
{{ $t('app.update') }}
</a>
</div>
@@ -148,7 +164,7 @@
<a class="btn" href="" @click.prevent="closeCreateTypeModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="storeType()">
<a v-cy-name="'add-type-button'" class="btn btn-primary" href="" @click.prevent="storeType()">
{{ $t('app.save') }}
</a>
</div>
@@ -172,7 +188,7 @@
<a class="btn" href="" @click.prevent="closeUpdateTypeModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="updateType()">
<a v-cy-name="'update-type-button'" class="btn btn-primary" href="" @click.prevent="updateType()">
{{ $t('app.update') }}
</a>
</div>
@@ -198,7 +214,7 @@
<a class="btn" href="" @click.prevent="closeDeleteCategoryModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="destroyCategory()">
<a v-cy-name="'delete-category-button'" class="btn btn-primary" href="" @click.prevent="destroyCategory()">
{{ $t('app.delete') }}
</a>
</div>
@@ -224,7 +240,7 @@
<a class="btn" href="" @click.prevent="closeDeleteTypeModal()">
{{ $t('app.cancel') }}
</a>
<a class="btn btn-primary" href="" @click.prevent="destroyType()">
<a v-cy-name="'delete-type-button'" class="btn btn-primary" href="" @click.prevent="destroyType()">
{{ $t('app.delete') }}
</a>
</div>
@@ -273,6 +289,7 @@ export default {
updateCategoryForm: {
id: '',
name: '',
activity_type_category_id: '',
errors: []
},
@@ -359,9 +376,10 @@ export default {
this.$refs.deleteTypeModal.open();
},
showEditType(type) {
showEditType(type, categoryId) {
this.updateTypeForm.id = type.id;
this.updateTypeForm.name = type.name;
this.updateTypeForm.activity_type_category_id = categoryId;
this.$refs.updateTypeModal.open();
},
@@ -21,7 +21,7 @@
<p>{{ $t('settings.recovery_help_intro') }}</p>
<p :class="[ dirltr ? 'ml3' : 'mr3' ]">
<span v-for="code in codes" :key="code.id" :cy-name="'recovery-' + code.id">
<span v-for="code in codes" :key="code.id" v-cy-name="'recovery-' + code.id">
<pre class="code" :class="[ code.used ? 'used' : '' ]" :title="[ code.used ? usedHelp : '']">{{ code.recovery }}</pre>
</span>
</p>
@@ -29,8 +29,8 @@
</div>
<div class="table-cell actions">
<a
v-cy-name="'u2fkey-delete-button-' + key.id"
class="pointer"
:cy-name="'u2fkey-delete-button-' + key.id"
@click.prevent="showDeleteModal(key.id)"
>
{{ $t('app.delete') }}
@@ -174,9 +174,9 @@
{{ $t('app.cancel') }}
</a>
<a
v-cy-name="'modal-delete-u2fkey-button-' + keyToTrash"
class="btn"
href=""
:cy-name="'modal-delete-u2fkey-button-' + keyToTrash"
@click.prevent="u2fRemove(keyToTrash)"
>
{{ $t('app.delete') }}
+21
View File
@@ -0,0 +1,21 @@
/**
* Add cy-name and cy-items directives.
* These are only active on local or testing environment.
*/
function testingDirective(el, binding, vnode) {
if (window.Laravel.env != 'production') {
var value = '';
try {
value = function(expr) {
return eval(expr);
}.call(vnode.context, ' with(this) { ' + binding.expression + ' } ');
} catch (e) {
value = binding.value;
}
el.setAttribute(binding.name, value.toString());
}
}
Vue.directive('cy-items', testingDirective);
Vue.directive('cy-name', testingDirective);
@@ -21,6 +21,7 @@
'htmldir' => htmldir(),
'profileDefaultView' => auth()->user()->profile_active_tab,
'timezone' => auth()->user()->timezone,
'env' => \App::environment(),
]); !!}
</script>
</head>
+2 -2
View File
@@ -22,7 +22,7 @@
<div class="col-12 debts-list">
<ul class="table">
<ul class="table" cy-name="debts-body" cy-items="{{ $contact->debts->implode('id', ',') }}">
@foreach($contact->debts as $debt)
<li class="table-row" cy-name="debt-item-{{ $debt->id }}">
<div class="table-cell date">
@@ -52,7 +52,7 @@
<form method="POST" action="{{ route('people.debts.destroy', [$contact, $debt]) }}">
@method('DELETE')
@csrf
<confirm message="{{ trans('people.debt_delete_confirmation') }}" cy-name="delete-debt-button-{{ $debt->id }}">
<confirm message="{{ trans('people.debt_delete_confirmation') }}" cy-name="delete-debt-button-{{ $debt->id }}" :name="'delete-debt'">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</confirm>
</form>
-5
View File
@@ -162,9 +162,4 @@
</form>
</div>
</div>
<form method="POST" action="{{ route('people.destroy', $contact) }}" id="contact-delete-form" class="hidden">
@method('DELETE')
@csrf
</form>
@endsection
+1 -1
View File
@@ -74,7 +74,7 @@
<form method="POST" action="{{ route('people.destroy', $contact) }}">
@method('DELETE')
@csrf
<confirm message="{{ trans('people.people_delete_confirmation') }}">
<confirm id="link-delete-contact" message="{{ trans('people.people_delete_confirmation') }}">
{{ trans('people.people_delete_message') }}
</confirm>
</form>
+4 -3
View File
@@ -8,11 +8,12 @@ DB_TEST_DATABASE=monica
DB_TEST_USERNAME=root
DB_TEST_PASSWORD=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=
APP_EMAIL_NEW_USERS_NOTIFICATION=
CACHE_DRIVER=array
SESSION_DRIVER=file
QUEUE_CONNECTION=sync
LOG_CHANNEL=testing
BROADCAST_DRIVER=log
MFA_ENABLED=true
DAV_ENABLED=true
-6
View File
@@ -1,6 +0,0 @@
{
"reporterEnabled": "spec, mocha-junit-reporter",
"mochaJunitReporterReporterOptions": {
"mochaFile": "results/junit/cypress/results.[hash].xml"
}
}
+4
View File
@@ -20,3 +20,7 @@ if [ "$STRIPE_SECRET" == "\$(STRIPE_SECRET)" ]; then
echo -e "\033[0;36mFix STRIPE_SECRET\033[0;37m"
export STRIPE_SECRET=
fi
if [ "$CYPRESS_RECORD_KEY" == "\$(CYPRESS_RECORD_KEY)" ]; then
echo -e "\033[0;36mFix CYPRESS_RECORD_KEY\033[0;37m"
export CYPRESS_RECORD_KEY=
fi
+8 -42
View File
@@ -3,8 +3,6 @@
namespace Tests\BrowserFeature;
use Tests\DuskTestCase;
use App\Models\User\User;
use App\Services\User\AcceptPolicy;
use Tests\Browser\Pages\ImportVCardUpload;
class UploadVCardTest extends DuskTestCase
@@ -17,16 +15,8 @@ class UploadVCardTest extends DuskTestCase
*/
public function test_upload_vcard_is_accessible_from_add_contact_view()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function ($browser) use ($user) {
$browser->loginAs($user)
$this->browse(function ($browser) {
$browser->login()
->visit('/people/add')
->assertSee('import your contacts');
@@ -43,16 +33,8 @@ class UploadVCardTest extends DuskTestCase
*/
public function test_import_button_leads_to_import_screen()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function ($browser) use ($user) {
$browser->loginAs($user)
$this->browse(function ($browser) {
$browser->login()
->visit('/settings/import')
->clickLink('Import vCard')
->assertPathIs('/settings/import/upload')
@@ -68,16 +50,8 @@ class UploadVCardTest extends DuskTestCase
*/
public function test_user_can_import_contacts_from_a_vcf_card()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function ($browser) use ($user) {
$browser->loginAs($user)
$this->browse(function ($browser) {
$browser->login()
->visit('/settings/import')
->clickLink('Import vCard')
->attach('vcard', base_path('tests/stubs/single_vcard_stub.vcard'))
@@ -95,16 +69,8 @@ class UploadVCardTest extends DuskTestCase
*/
public function test_user_see_error_when_importing_broken_vcard()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function ($browser) use ($user) {
$browser->loginAs($user)
$this->browse(function ($browser) {
$browser->login()
->visit('/settings/import')
->clickLink('Import vCard')
->attach('vcard', base_path('tests/stubs/broken_vcard_stub.vcard'))
+2 -12
View File
@@ -3,9 +3,7 @@
namespace Tests\Browser\Settings;
use Tests\DuskTestCase;
use App\Models\User\User;
use Laravel\Dusk\Browser;
use App\Services\User\AcceptPolicy;
use Tests\Browser\Pages\SettingsDAV;
class DAVControllerTest extends DuskTestCase
@@ -15,16 +13,8 @@ class DAVControllerTest extends DuskTestCase
*/
public function test_it_has_dav_url()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->loginAs($user)
$this->browse(function (Browser $browser) {
$browser->login()
->visit(new SettingsDAV)
->assertVisible('dav_url_base')
->assertSourceHas(config('app.url').'/dav');
+20 -107
View File
@@ -4,9 +4,7 @@ namespace Tests\Browser\Settings;
use Zxing\QrReader;
use Tests\DuskTestCase;
use App\Models\User\User;
use Laravel\Dusk\Browser;
use App\Services\User\AcceptPolicy;
use Illuminate\Console\Application;
use Tests\Browser\Pages\SettingsSecurity;
use Tests\Browser\Pages\DashboardValidate2fa;
@@ -19,7 +17,6 @@ class MultiFAControllerTest extends DuskTestCase
public function cleanup()
{
exec(Application::formatCommandString('2fa:deactivate --force --email=admin@admin.com'), $output);
//$this->log(implode($output));
}
/**
@@ -28,16 +25,8 @@ class MultiFAControllerTest extends DuskTestCase
*/
public function testHasSettings2faEnableLink()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->loginAs($user)
$this->browse(function (Browser $browser) {
$browser->login()
->visit(new SettingsSecurity)
->assertSeeLink('Enable Two Factor Authentication');
});
@@ -49,16 +38,8 @@ class MultiFAControllerTest extends DuskTestCase
*/
public function testHasSettingsWebAuthnEnableLink()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->loginAs($user)
$this->browse(function (Browser $browser) {
$browser->login()
->visit(new SettingsSecurity)
->assertSeeLink('Add a new security key');
});
@@ -72,16 +53,8 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->loginAs($user)
$this->browse(function (Browser $browser) {
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Add a new U2F security key')
@@ -98,16 +71,8 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$browser->loginAs($user)
$this->browse(function (Browser $browser) {
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -126,17 +91,9 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$this->browse(function (Browser $browser) {
$browser =
$browser->loginAs($user)
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -183,17 +140,9 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$this->browse(function (Browser $browser) {
$browser =
$browser->loginAs($user)
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -218,17 +167,9 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$this->browse(function (Browser $browser) {
$browser =
$browser->loginAs($user)
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -272,13 +213,7 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$user = call_user_func(Browser::$userResolver);
$this->browse(function (Browser $browser) use ($user) {
$browser =
@@ -313,13 +248,7 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$user = call_user_func(Browser::$userResolver);
$this->browse(function (Browser $browser) use ($user) {
$browser =
@@ -354,17 +283,9 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$this->browse(function (Browser $browser) {
$browser =
$browser->loginAs($user)
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -398,17 +319,9 @@ class MultiFAControllerTest extends DuskTestCase
{
$this->markTestIncomplete('Ignore 2fa tests for now.');
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
app(AcceptPolicy::class)->execute([
'account_id' => $user->account_id,
'user_id' => $user->id,
'ip_address' => null,
]);
$this->browse(function (Browser $browser) use ($user) {
$this->browse(function (Browser $browser) {
$browser =
$browser->loginAs($user)
$browser->login()
->visit(new SettingsSecurity)
->scrollTo('two_factor_link')
->clickLink('Enable Two Factor Authentication')
@@ -1,6 +1,6 @@
<?php
namespace Tests\Jobs;
namespace Tests\Commands;
use Tests\TestCase;
use App\Models\User\User;
+1 -1
View File
@@ -1,6 +1,6 @@
<?php
namespace Tests\Jobs;
namespace Tests\Commands;
use Carbon\Carbon;
use Tests\TestCase;
+1 -1
View File
@@ -1,6 +1,6 @@
<?php
namespace Tests\Jobs;
namespace Tests\Commands;
use Carbon\Carbon;
use Tests\TestCase;
@@ -0,0 +1,27 @@
<?php
namespace Tests\Commands;
use Tests\TestCase;
use App\Models\User\User;
use App\Models\Account\Account;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class SetupFrontEndTestUserTest extends TestCase
{
use DatabaseTransactions;
/** @test */
public function it_create_a_test_user()
{
$this->withoutMockingConsoleOutput();
$accountCount = Account::count();
$userCount = User::count();
$exitCode = $this->artisan('setup:frontendtestuser');
$this->assertEquals($accountCount + 1, Account::count());
$this->assertEquals($userCount + 1, User::count());
}
}
+23
View File
@@ -3,7 +3,10 @@
namespace Tests;
use Tests\Traits\SignIn;
use App\Models\User\User;
use Laravel\Dusk\Browser;
use App\Services\User\AcceptPolicy;
use Tests\Traits\CreatesApplication;
use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
@@ -51,6 +54,26 @@ abstract class DuskTestCase extends BaseTestCase
}
}
/**
* Return the default user to authenticate.
*
* @return \App\User|int|null
*/
protected function user()
{
$user = factory(User::class)->create();
$user->account->populateDefaultFields();
$user->account->update(['has_access_to_paid_version_for_free' => true]);
app(AcceptPolicy::class)->execute([
'account_id' => $user->account->id,
'user_id' => $user->id,
'ip_address' => null,
]);
return $user;
}
public function hasDivAlert(Browser $browser)
{
$res = $browser->elements('alert');
+1
View File
@@ -2,6 +2,7 @@
namespace Tests;
use Tests\Traits\CreatesApplication;
use Illuminate\Foundation\Testing\TestResponse;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
@@ -1,6 +1,6 @@
<?php
namespace Tests;
namespace Tests\Traits;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Hash;
@@ -15,7 +15,7 @@ trait CreatesApplication
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app = require __DIR__.'/../../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
+7 -21
View File
@@ -1,25 +1,11 @@
describe('Login', function () {
beforeEach(function () {
cy.exec('php artisan setup:frontendtesting')
})
it('should not let user sign in with a non-existing account', function () {
cy.visit('/')
cy.visit('/');
cy.get('input[name=email]').type('impossibru@test.com')
cy.get('input[name=password]').type('testtest')
cy.get('button[type=submit]').click()
cy.get('input[name=email]').type('impossibru@test.com');
cy.get('input[name=password]').type('testtest');
cy.get('button[type=submit]').click();
cy.get('.alert').should('exist')
})
it('should sign in into the application', function () {
cy.visit('/')
cy.get('input[name=email]').type('admin@admin.com')
cy.get('input[name=password]').type('admin')
cy.get('button[type=submit]').click()
cy.url().should('include', '/dashboard')
})
})
cy.get('.alert').should('exist');
});
});
+17 -28
View File
@@ -1,8 +1,6 @@
describe('Signup', function () {
beforeEach(function () {
cy.exec('php artisan setup:frontendtesting')
})
var faker = require('faker');
describe('Signup', function () {
// @TODO: get emails from Mailtrap with their API and click on the confirmation
// link
//
@@ -25,30 +23,21 @@ describe('Signup', function () {
// cy.contains('Login to your account')
// })
it('should block registration if policy is not accepted', function () {
cy.visit('/register')
//it('should block registration if policy is not accepted', function () {
// cy.register(faker.name.firstName(), faker.name.lastName(), faker.internet.password(), faker.internet.email(), false);
// cy.get('.alert').should('exist');
//});
cy.get('input[name=first_name]').type('test')
cy.get('input[name=last_name]').type('test')
cy.get('input[name=password]').type('testtest')
cy.get('input[name=password_confirmation]').type('testtest')
cy.get('button[type=submit]').click()
cy.get('.alert').should('exist')
})
it('should block registration if email is invalid', function () {
cy.visit('/register')
it('should block registration if email is already used', function () {
const email = faker.internet.email();
// test email address
cy.get('.alert').should('not.exist')
cy.get('input[name=first_name]').type('test')
cy.get('input[name=last_name]').type('test')
cy.get('input[name=password]').type('testtest')
cy.get('input[name=password_confirmation]').type('testtest')
cy.get('input[name=email]').type('test@test')
cy.get('input[name=policy]').click()
cy.get('button[type=submit]').click()
cy.get('.alert').should('exist')
})
})
cy.register(faker.name.firstName(), faker.name.lastName(), faker.internet.password(), email, true);
cy.get('.alert').should('not.exist');
cy.get('[data-cy=header-link-logout]').click();
cy.register(faker.name.firstName(), faker.name.lastName(), faker.internet.password(), email, true);
cy.get('.alert').should('exist');
});
});
+24 -19
View File
@@ -1,30 +1,35 @@
describe('Activities', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage an activity', function () {
cy.url().should('include', '/people/h:')
cy.get('[cy-name=activities-blank-state]').should('be.visible')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=activities-blank-state]').should('be.visible');
// add an activity
cy.createActivity()
cy.createActivity();
// edit an activity
cy.get('[cy-name=edit-activity-button-1]').click()
cy.url().should('include', '/activities/h:')
cy.get('[cy-name=activities-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
cy.get('[name=summary]').clear()
cy.get('[name=summary]').type('This is another summary')
cy.get('[cy-name=save-activity-button]').click()
cy.get('[cy-name=edit-activity-button-'+item+']').click();
cy.get('[cy-name=activity-body-1]').should('exist')
cy.get('[cy-name=activity-body-1]').should('contain', 'This is another summary')
cy.get('[name=summary]').clear();
cy.get('[name=summary]').type('This is another summary');
cy.get('[cy-name=save-activity-button]').click();
// delete an activity
cy.get('[cy-name=delete-activity-button-1]').click()
cy.get('[cy-name=activities-blank-state]').should('be.visible')
cy.get('[cy-name=activity-body-1]').should('not.exist')
})
})
cy.get('[cy-name=activity-body-'+item+']').should('exist');
cy.get('[cy-name=activity-body-'+item+']').should('contain', 'This is another summary');
// delete an activity
cy.get('[cy-name=delete-activity-button-'+item+']').click();
cy.wait(10);
cy.get('[cy-name=confirm-delete-activity]').should('be.visible').click();
cy.get('[cy-name=activities-blank-state]').should('be.visible');
cy.get('[cy-name=activity-body-'+item+']').should('not.exist');
});
});
});
+28 -18
View File
@@ -1,25 +1,35 @@
var _ = require('lodash');
describe('Calls', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a call', function () {
cy.url().should('include', '/people/h:')
cy.get('[cy-name=calls-blank-state]').should('exist')
cy.get('#logCallModal').should('not.be.visible')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=calls-blank-state]').should('exist');
cy.get('[cy-name=log-call-form]').should('not.be.visible');
// add a call
cy.get('[cy-name=add-call-button]').click()
cy.get('#logCallModal').should('be.visible')
cy.get('[cy-name=save-call-button]').click()
cy.get('[cy-name=calls-blank-state]').should('not.exist')
cy.get('[cy-name=call-body-1]').should('exist')
cy.get('[cy-name=call-body-1]').should('contain', 'John')
cy.get('[cy-name=add-call-button]').click();
cy.get('[cy-name=log-call-form]').should('be.visible');
cy.get('[cy-name=save-call-button]').click();
cy.get('[cy-name=calls-blank-state]').should('not.exist');
// delete a call
cy.get('[cy-name=edit-call-button-1]').should('be.visible')
cy.get('[cy-name=edit-call-button-1]').click()
cy.get('[cy-name=calls-blank-state]').should('exist')
})
})
cy.get('[cy-name=calls-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (items) {
let item = _.last(items.split(','));
cy.get('[cy-name=call-body-'+item+']').should('exist');
cy.get('[cy-name=call-body-'+item+']').should('contain', 'John');
// delete a call
cy.get('[cy-name=delete-call-button-'+item+']').should('be.visible');
cy.get('[cy-name=delete-call-button-'+item+']').click();
cy.get('[cy-name=delete-call-confirm-button-'+item+']').should('be.visible');
cy.get('[cy-name=delete-call-confirm-button-'+item+']').click();
cy.get('[cy-name=calls-blank-state]').should('exist');
});
});
});
+59 -62
View File
@@ -1,98 +1,95 @@
describe('Contacts', function () {
beforeEach(function () {
cy.login()
})
cy.login();
});
it('lets you add a contact', function () {
cy.createContact('John', 'Doe', 'Man')
cy.url().should('include', '/people/h:')
cy.get('h1').should('contain', 'John Doe')
})
cy.createContact('John', 'Doe', 'Man');
cy.url().should('include', '/people/h:');
cy.get('h1').should('contain', 'John Doe');
});
it('lets you add two contacts in a row', function () {
cy.createContact('John', 'Doe', 'Man', 'save_and_add_another')
cy.url().should('include', '/people/add')
})
cy.createContact('John', 'Doe', 'Man', 'save_and_add_another');
cy.url().should('include', '/people/add');
});
it('requires at least a firstname and a gender to add a contact', function () {
cy.visit('/people')
cy.get('#button-add-contact').click()
cy.get('button[name=save]').click()
cy.url().should('include', '/people/add')
it('requires at least a firstname to add a contact', function () {
cy.visit('/people');
cy.get('#button-add-contact').click();
cy.get('button[name=save]').click();
cy.url().should('include', '/people/add');
cy.get('input[name=first_name]').type('John')
cy.get('button[name=save]').click()
cy.url().should('include', '/people/add')
cy.get('input[name=first_name]').type('John');
cy.get('select[name=gender]').select('Man');
cy.get('button[name=save]').click();
cy.get('select[name=gender]').select('Man')
cy.get('button[name=save]').click()
cy.url().should('include', '/people/h:')
cy.get('h1').should('contain', 'John')
})
cy.url().should('include', '/people/h:');
cy.get('h1').should('contain', 'John');
});
it('lets you edit a contact', function () {
cy.createContact('John', 'Doe', 'Man')
cy.createContact('John', 'Doe', 'Man');
cy.get('#button-edit-contact').click();
cy.url().should('include', '/edit')
cy.url().should('include', '/edit');
cy.get('input[name=firstname]').should('have.value', 'John')
cy.get('input[name=lastname]').should('have.value', 'Doe')
cy.get('select[name=gender]').should('have.value', '1')
cy.get('input[name=firstname]').should('have.value', 'John');
cy.get('input[name=lastname]').should('have.value', 'Doe');
//TO FIX cy.get('select[name=gender]').should('have.text', 'Man')
cy.get('input[name=firstname]').clear()
cy.get('input[name=firstname]').type('Jane')
cy.get('input[name=lastname]').clear()
cy.get('button[name=save]').click()
cy.get('input[name=firstname]').clear();
cy.get('input[name=firstname]').type('Jane');
cy.get('input[name=lastname]').clear();
cy.get('button[name=save]').click();
cy.url().should('include', '/people/h:')
cy.get('h1').should('contain', 'Jane')
})
cy.url().should('include', '/people/h:');
cy.get('h1').should('contain', 'Jane');
});
it('lets you delete a contact', function () {
cy.createContact('John', 'Doe', 'Man')
cy.createContact('John', 'Doe', 'Man');
cy.visit('/people')
cy.get('.people-list-item').should('contain', 'John Doe')
cy.visit('/people');
cy.get('.people-list-item').should('contain', 'John Doe');
// this gets the first content of the list
cy.get('li.people-list-item.bg-white.pointer').click()
cy.get('tr.people-list-item.bg-white.pointer').click();
cy.get('#link-delete-contact').click()
cy.get('#link-delete-contact').click();
// cypress auto accepts window alerts (confirm or alert)
cy.url().should('include', '/people')
cy.url().should('include', '/people');
cy.visit('/people')
cy.get('.people-list-item').should('not.contain', 'John')
})
cy.visit('/people');
cy.get('.people-list-item').should('not.contain', 'John');
});
it('lets you add a contact as favorite', function () {
cy.createContact('John', 'Doe', 'Man')
cy.createContact('John', 'Doe', 'Man');
cy.visit('/people')
cy.visit('/people');
// this gets the first content of the list
cy.get('li.people-list-item.bg-white.pointer').click()
cy.get('tr.people-list-item.bg-white.pointer').click();
// tests if the favorite button can be toggled
cy.get('[cy-name=set-favorite]').should('be.visible')
cy.get('[cy-name=set-favorite]').click()
cy.get('[cy-name=set-favorite]').should('not.be.visible')
cy.get('[cy-name=unset-favorite]').should('be.visible')
cy.get('[cy-name=unset-favorite]').click()
cy.get('[cy-name=set-favorite]').should('be.visible')
cy.get('[cy-name=set-favorite]').should('be.visible');
cy.get('[cy-name=set-favorite]').click();
cy.get('[cy-name=set-favorite]').should('not.be.visible');
cy.get('[cy-name=unset-favorite]').should('be.visible');
cy.get('[cy-name=unset-favorite]').click();
cy.get('[cy-name=set-favorite]').should('be.visible');
// test to see if a contact appears on top of the contact list if favorited
cy.get('[cy-name=set-favorite]').click()
cy.visit('/dashboard')
cy.createContact('Abc', 'Abc', 'Man')
cy.visit('/people')
cy.get('[cy-name=set-favorite]').click();
cy.visit('/dashboard');
cy.createContact('Abc', 'Abc', 'Man');
cy.visit('/people');
cy.get('.people-list-item span').should('contain', 'John Doe')
cy.get('.people-list-item svg').should('be.visible')
cy.get('.people-list-item span').should('contain', 'John Doe');
cy.get('.people-list-item svg').should('be.visible');
cy.get('.people-list-item').should('contain', 'Abc Abc')
})
})
cy.get('.people-list-item').should('contain', 'Abc Abc');
});
});
+16 -16
View File
@@ -1,27 +1,27 @@
describe('Conversations', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a conversation', function () {
cy.get('[cy-name=conversation-blank-state]').should('be.visible')
cy.get('[cy-name=conversation-blank-state]').should('be.visible');
// add a conversation
cy.visit('/people')
cy.visit('/people');
// this gets the first content of the list
cy.get('li.people-list-item.bg-white.pointer').click()
cy.get('tr.people-list-item.bg-white.pointer').click();
cy.get('[cy-name=add-conversation-button]').should('be.visible')
cy.get('[cy-name=add-conversation-button]').click()
cy.url().should('include', '/conversations/create')
cy.get('[cy-name=add-conversation-button]').should('be.visible');
cy.get('[cy-name=add-conversation-button]').click();
cy.url().should('include', '/conversations/create');
cy.get('[name=contactFieldTypeId]').select('3')
cy.get('[name=content_1]').type('This is a message')
cy.get('[cy-name=save-conversation-button]').click()
cy.get('[name=contactFieldTypeId]').select('Phone');
cy.get('[name=content_1]').type('This is a message');
cy.get('[cy-name=save-conversation-button]').click();
cy.url().should('include', '/people/h:')
cy.get('[cy-name=conversation-blank-state]').should('not.be.visible')
})
})
cy.url().should('include', '/people/h:');
cy.get('[cy-name=conversation-blank-state]').should('not.be.visible');
});
});
+34 -28
View File
@@ -1,40 +1,46 @@
describe('Debts', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a debt', function () {
cy.url().should('include', '/people/h:')
cy.get('[cy-name=debt-blank-state]').should('be.visible')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=debt-blank-state]').should('be.visible');
// add a debt
cy.get('[cy-name=add-debt-button]').should('be.visible')
cy.get('[cy-name=add-debt-button]').click()
cy.url().should('include', '/debts/create')
cy.get('[cy-name=add-debt-button]').should('be.visible');
cy.get('[cy-name=add-debt-button]').click();
cy.url().should('include', '/debts/create');
cy.get('[name=amount]').type('123')
cy.get('[cy-name=save-debt-button]').click()
cy.get('[name=amount]').type('123');
cy.get('[cy-name=save-debt-button]').click();
cy.url().should('include', '/people/h:')
cy.get('[cy-name=debt-blank-state]').should('not.be.visible')
cy.get('[cy-name=debt-item-1]').should('exist')
cy.get('[cy-name=debt-item-1]').should('contain', '123')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=debt-blank-state]').should('not.be.visible');
// edit a debt
cy.get('[cy-name=edit-debt-button-1]').click()
cy.url().should('include', '/edit')
cy.get('[cy-name=debts-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
cy.get('[name=amount]').clear()
cy.get('[name=amount]').type('234')
cy.get('[cy-name=save-debt-button]').click()
cy.get('[cy-name=debt-item-'+item+']').should('exist');
cy.get('[cy-name=debt-item-'+item+']').should('contain', '123');
cy.get('[cy-name=debt-item-1]').should('exist')
cy.get('[cy-name=debt-item-1]').should('contain', '234')
// edit a debt
cy.get('[cy-name=edit-debt-button-'+item+']').click();
cy.url().should('include', '/edit');
// delete a debt
cy.get('[cy-name=delete-debt-button-1]').click()
cy.get('[cy-name=debt-blank-state]').should('be.visible')
cy.get('[cy-name=debt-item-1]').should('not.exist')
})
})
cy.get('[name=amount]').clear();
cy.get('[name=amount]').type('234');
cy.get('[cy-name=save-debt-button]').click();
cy.get('[cy-name=debt-item-'+item+']').should('exist');
cy.get('[cy-name=debt-item-'+item+']').should('contain', '234');
// delete a debt
cy.get('[cy-name=delete-debt-button-'+item+']').click();
cy.get('[cy-name=confirm-delete-debt]').should('be.visible').click();
cy.get('[cy-name=debt-blank-state]').should('be.visible');
cy.get('[cy-name=debt-item-'+item+']').should('not.exist');
});
});
});
+38 -27
View File
@@ -1,39 +1,50 @@
/*
Gift page has change recently a lot, let rewrite this test later ...
###
describe('Gifts', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a gift', function () {
cy.url().should('include', '/people/h:')
cy.url().should('include', '/people/h:');
// add a gift
cy.get('[cy-name=add-gift-button]').should('be.visible')
cy.get('[cy-name=add-gift-button]').click()
cy.url().should('include', '/gifts/create')
cy.get('[cy-name=add-gift-button]').should('be.visible');
cy.get('[cy-name=add-gift-button]').click();
cy.url().should('include', '/gifts/create');
cy.get('[name=name]').type('This is a gift')
cy.get('[cy-name=save-gift-button]').click()
cy.get('[name=name]').type('This is a gift');
cy.get('[cy-name=save-gift-button]').click();
cy.url().should('include', '/people/h:')
cy.get('[cy-name=gift-idea-item-1]').should('exist')
cy.get('[cy-name=gift-idea-item-1]').should('contain', 'This is a gift')
cy.url().should('include', '/people/h:');
// edit a gift
cy.get('[cy-name=edit-gift-button-1]').click()
cy.url().should('include', '/gifts/1/edit')
cy.get('[cy-name=gift-ideas-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
cy.get('[name=name]').clear()
cy.get('[name=name]').type('This is another gift')
cy.get('[cy-name=save-gift-button]').click()
cy.get('[cy-name=gift-idea-item-'+item+']').should('exist');
cy.get('[cy-name=gift-idea-item-'+item+']').should('contain', 'This is a gift');
cy.get('[cy-name=gift-idea-item-1]').should('exist')
cy.get('[cy-name=gift-idea-item-1]').should('contain', 'This is another gift')
// edit a gift
cy.get('[cy-name=edit-gift-button-'+item+']').click();
cy.url().should('include', '/gifts/'+item+'/edit');
// delete an gift
cy.get('[cy-name=delete-gift-button-1]').click()
cy.get('[cy-name=modal-delete-gift-button-1]').click()
cy.get('[cy-name=activities-blank-state]').should('be.visible')
cy.get('[cy-name=gift-idea-item-1]').should('not.exist')
})
})
cy.get('[name=name]').clear();
cy.get('[name=name]').type('This is another gift');
cy.get('[cy-name=save-gift-button]').click();
cy.get('[cy-name=gift-idea-item-'+item+']').should('exist');
cy.get('[cy-name=gift-idea-item-'+item+']').should('contain', 'This is another gift');
// delete an gift
cy.get('[cy-name=delete-gift-button-'+item+']').click();
cy.get('[cy-name=modal-delete-gift-button-'+item+']').click();
cy.get('[cy-name=activities-blank-state]').should('be.visible');
cy.get('[cy-name=gift-idea-item-'+item+']').should('not.exist');
});
});
});
*/
+31 -27
View File
@@ -1,41 +1,45 @@
describe('Notes', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a note', function () {
cy.url().should('include', '/people/h:')
cy.get('[cy-name=add-note-button]').should('not.be.visible')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=add-note-button]').should('not.be.visible');
// add a note
cy.get('[cy-name=add-note-textarea]').click()
cy.get('[cy-name=add-note-button]').should('be.visible')
cy.get('[cy-name=add-note-textarea]').click();
cy.get('[cy-name=add-note-button]').should('be.visible');
cy.get('[cy-name=add-note-textarea]').type('This is a note')
cy.get('[cy-name=add-note-button]').click()
cy.get('[cy-name=add-note-textarea]').type('This is a note');
cy.get('[cy-name=add-note-button]').click();
cy.get('[cy-name=note-body-1]').should('contain', 'This is a note')
cy.get('[cy-name=notes-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
cy.get('[cy-name=edit-note-body-1]').should('not.be.visible')
cy.get('[cy-name=note-body-'+item+']').should('contain', 'This is a note');
// edit a note
cy.get('[cy-name=edit-note-button-1]').click()
cy.get('[cy-name=edit-note-body-1]').should('be.visible')
cy.get('[cy-name=edit-note-body-'+item+']').should('not.be.visible');
cy.get('[cy-name=edit-note-body-1]').clear()
cy.get('[cy-name=edit-note-body-1]').type('This is another note')
cy.get('[cy-name=edit-mode-note-button-1]').click()
// edit a note
cy.get('[cy-name=edit-note-button-'+item+']').click();
cy.get('[cy-name=edit-note-body-'+item+']').should('be.visible');
cy.get('[cy-name=edit-note-body-1]').should('not.be.visible')
cy.get('[cy-name=note-body-1]').should('contain', 'This is another note')
cy.get('[cy-name=edit-note-body-'+item+']').clear();
cy.get('[cy-name=edit-note-body-'+item+']').type('This is another note');
cy.get('[cy-name=edit-mode-note-button-'+item+']').click();
// delete a note
cy.get('#modal-delete-note').should('not.be.visible')
cy.get('[cy-name=delete-note-button-1]').click()
cy.get('#modal-delete-note').should('be.visible')
cy.get('[cy-name=delete-mode-note-button-1]').click()
cy.get('[cy-name=edit-note-body-'+item+']').should('not.be.visible');
cy.get('[cy-name=note-body-'+item+']').should('contain', 'This is another note');
cy.get('[cy-name=note-body-1]').should('not.exist')
})
})
// delete a note
cy.get('[cy-name=modal-delete-note]').should('not.be.visible');
cy.get('[cy-name=delete-note-button-'+item+']').click();
cy.get('[cy-name=modal-delete-note]').should('be.visible');
cy.get('[cy-name=delete-mode-note-button-'+item+']').click();
cy.get('[cy-name=note-body-'+item+']').should('not.exist');
});
});
});
+21 -18
View File
@@ -1,28 +1,31 @@
describe('Tasks', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a task', function () {
cy.url().should('include', '/people/h:')
cy.get('[cy-name=task-blank-state]').should('be.visible')
cy.url().should('include', '/people/h:');
cy.get('[cy-name=task-blank-state]').should('be.visible');
// add a task
cy.get('[cy-name=add-task-button]').click()
cy.get('[cy-name=task-add-view]').should('be.visible')
cy.get('[cy-name=add-task-button]').click();
cy.get('[cy-name=task-add-view]').should('be.visible');
cy.get('[cy-name=task-add-title]').type('This is a task')
cy.get('[cy-name=save-task-button]').click()
cy.get('[cy-name=task-add-view]').should('not.be.visible')
cy.get('[cy-name=task-add-title]').type('This is a task');
cy.get('[cy-name=save-task-button]').click();
cy.get('[cy-name=task-item-1]').should('exist')
cy.get('[cy-name=task-item-1]').should('contain', 'This is a task')
cy.get('[cy-name=tasks-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
// edit a task
cy.get('[cy-name=task-toggle-edit-mode]').click()
cy.get('[cy-name=task-delete-button-1]').click()
cy.get('[cy-name=task-item-'+item+']').should('exist');
cy.get('[cy-name=task-item-'+item+']').should('contain', 'This is a task');
cy.get('[cy-name=task-blank-state]').should('be.visible')
})
})
// edit a task
cy.get('[cy-name=task-toggle-edit-mode]').click();
cy.get('[cy-name=task-delete-button-'+item+']').click();
cy.get('[cy-name=task-blank-state]').should('be.visible');
});
});
});
+56 -34
View File
@@ -1,51 +1,73 @@
describe('Journal entries', function () {
beforeEach(function () {
cy.login()
cy.createContact('John', 'Doe', 'Man')
})
cy.login();
cy.createContact('John', 'Doe', 'Man');
});
it('lets you manage a journal entry', function () {
cy.visit('/journal')
cy.get('[cy-name=journal-blank-state]').should('be.visible')
cy.visit('/journal');
cy.get('[cy-name=journal-blank-state]').should('be.visible');
// add a journal entry
cy.get('[cy-name=add-entry-button]').should('be.visible')
cy.get('[cy-name=add-entry-button]').click()
cy.url().should('include', '/journal/add')
cy.get('[cy-name=add-entry-button]').should('be.visible');
cy.get('[cy-name=add-entry-button]').click();
cy.url().should('include', '/journal/add');
cy.get('[name=entry]').type('This is an entry')
cy.get('[cy-name=save-entry-button]').click()
cy.get('[name=entry]').type('This is an entry');
cy.get('[cy-name=save-entry-button]').click();
cy.url().should('include', '/journal')
cy.get('[cy-name=journal-blank-state]').should('not.be.visible')
cy.get('[cy-name=entry-body-1]').should('exist')
cy.get('[cy-name=entry-body-1]').should('contain', 'This is an entry')
cy.url().should('include', '/journal');
cy.get('[cy-name=journal-blank-state]').should('not.be.visible');
// delete a journal entry
cy.get('[cy-name=entry-delete-button-1]').click()
cy.url().should('include', '/journal')
cy.get('[cy-name=entry-body-1]').should('not.exist')
})
cy.get('[cy-name=journal-entries-body]').should('be.visible')
.invoke('attr', 'cy-items').then(function (item) {
cy.get('[cy-name=journal-entries-body]')
.invoke('attr', 'cy-object-items').then(function (objItem) {
cy.get('[cy-name=entry-body-'+item+']').should('exist');
cy.get('[cy-name=entry-body-'+item+']').should('contain', 'This is an entry');
// delete a journal entry
cy.get('[cy-name=entry-delete-button-'+objItem+']').click();
cy.url().should('include', '/journal');
cy.get('[cy-name=entry-body-'+item+']').should('not.exist');
});
});
});
it('creates a journal entry when creating an activity', function () {
cy.createActivity()
cy.createActivity();
cy.visit('/journal')
cy.visit('/journal');
cy.get('[cy-name=journal-blank-state]').should('not.be.visible')
cy.get('[cy-name=entry-body-1]').should('exist')
cy.get('[cy-name=entry-body-1]').should('contain', 'This is a summary')
cy.get('[cy-name=entry-delete-button-1]').should('not.exist')
})
cy.get('[cy-name=journal-blank-state]').should('not.be.visible');
cy.get('[cy-name=journal-entries-body]').should('be.visible').then((entries) => {
let item = entries[0].getAttribute('cy-items');
let objItem = entries[0].getAttribute('cy-object-items');
cy.get('[cy-name=entry-body-'+item+']').should('exist');
cy.get('[cy-name=entry-body-'+item+']').should('contain', 'This is a summary');
cy.get('[cy-name=entry-delete-button-'+objItem+']').should('not.exist');
});
});
it('lets you rate your day', function () {
cy.visit('/journal')
cy.visit('/journal');
cy.get('[cy-name=journal-blank-state]').should('be.visible')
cy.get('[cy-name=sad-reaction-button]').click()
cy.get('[cy-name=journal-blank-state]').should('be.visible');
cy.get('[cy-name=entry-body-1]').should('exist')
//cy.get('[cy-name=entry-body-1]').should('contain', 'This is a summary')
cy.get('[cy-name=entry-delete-button-1]').should('exist')
})
})
cy.get('[cy-name=sad-reaction-button]').click();
cy.wait(10);
cy.get('[cy-name=comment]').should('be.visible');
cy.get('[cy-name=save-entry-button]').click();
cy.get('[cy-name=journal-entries-body]').should('be.visible').then((entries) => {
let item = entries[0].getAttribute('cy-items');
cy.get('[cy-name=entry-body-'+item+']').should('exist');
cy.get('[cy-name=entry-delete-button-'+item+']').should('exist');
});
});
});
+120 -70
View File
@@ -1,84 +1,134 @@
var _ = require('lodash');
describe('Settings: activity types', function () {
it('doesn\'t let you manage activity types if user is not premium', function () {
cy.login()
cy.visit('/settings/personalization')
cy.get('[cy-name=activity-type-premium-message]').should('be.visible')
cy.get('[cy-name=activity-type-edit-button]').should('not.exist')
})
it('doesn\'t let you manage activity types if user is not premium', function () {
cy.login();
cy.visit('/settings/personalization');
cy.get('[cy-name=activity-type-premium-message]').should('be.visible');
cy.get('[cy-name=activity-type-edit-button]').should('not.exist');
});
it('lets you manage an activity type category and activity type', function () {
cy.login()
it('lets you manage an activity type category and activity type', function () {
cy.login();
cy.visit('/');
// set account as premium
cy.get('body').invoke('attr', 'data-account-id').then(function ($accountId) {
cy.setPremium($accountId)
})
// set account as premium
cy.get('body').invoke('attr', 'data-account-id').then(function ($accountId) {
cy.setPremium($accountId);
});
// make sure that going premium removes restrictions
cy.visit('/settings/personalization')
cy.get('[cy-name=activity-type-premium-message]').should('not.be.visible')
cy.get('[cy-name=activity-types]').should('contain', 'did sport together')
// make sure that going premium removes restrictions
cy.visit('/settings/personalization');
cy.get('[cy-name=activity-type-premium-message]').should('not.be.visible');
cy.get('[cy-name=activity-types]').should('contain', 'played a sport together');
// add an activity type category
cy.get('[cy-name=add-activity-category-type-button]').click()
cy.get('.sweet-modal-overlay').should('be.visible')
cy.get('[name=add-category-name]').type('This is an activity type category')
cy.get('[cy-name=add-activity-type-category-button]').click()
// add an activity type category
cy.get('[cy-name=add-activity-type-category-button]').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=add-category-name]').type('This is an activity type category');
cy.get('[cy-name=add-activity-type-category-save-button]').click();
cy.wait(10);
cy.get('[cy-name=activity-types]').should('contain', 'This is an activity type category')
cy.get('[cy-name=activity-types]').should('contain', 'This is an activity type category');
cy.get('[cy-name=activity-type-categories]').invoke('attr', 'cy-items').then((items) => {
let item = _.last(items.split(','));
// edit an activity type category
cy.get('[cy-name=activity-type-category-edit-button-5]').click()
cy.get('.sweet-modal-overlay').should('be.visible')
cy.get('[name=update-category-name]').clear()
cy.get('[name=update-category-name]').type('This is still an activity type category')
cy.get('[cy-name=update-activity-type-category-button]').click()
cy.get('[cy-name=activity-types]').should('contain', 'This is still an activity type category')
// edit an activity type category
cy.get('[cy-name=activity-type-category-edit-button-'+item+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=update-category-name]').clear();
cy.get('[name=update-category-name]').type('This is still an activity type category');
cy.get('[cy-name=update-activity-type-category-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is still an activity type category');
// add an activity type
cy.get('[cy-name=add-activity-type-button-for-category-5]').click()
cy.get('.sweet-modal-overlay').should('be.visible')
cy.get('[name=add-type-name]').type('This is activity type 1')
cy.get('[cy-name=add-type-button]').click()
cy.get('[cy-name=activity-types]').should('contain', 'This is activity type 1')
// add an activity type
cy.get('[cy-name=add-activity-type-button-for-category-'+item+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=add-type-name]').type('This is activity type 1');
cy.get('[cy-name=add-type-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is activity type 1');
// mae sure the activity type exists on the Add activity page
cy.createContact('John', 'Doe', 'Man')
cy.get('[cy-name=add-activity-button]').click();
cy.get('#activity_type_id').should('contain', 'This is activity type 1')
// edit an activity type
cy.get('[cy-name=activity-types-'+item+']').invoke('attr', 'cy-items').then((items) => {
let aitem = _.last(items.split(','));
// edit an activity type
cy.visit('/settings/personalization')
cy.get('[cy-name=activity-type-edit-button-14]').click()
cy.get('.sweet-modal-overlay').should('be.visible')
cy.get('[name=update-type-name]').clear()
cy.get('[name=update-type-name]').type('This is modified activity type 1')
cy.get('[cy-name=update-type-button]').click()
cy.get('[cy-name=activity-types]').should('contain', 'This is modified activity type 1')
cy.get('[cy-name=activity-type-edit-button-'+aitem+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=update-type-name]').clear();
cy.get('[name=update-type-name]').type('This is modified activity type 1');
cy.get('[cy-name=update-type-button]').click();
cy.wait(10);
cy.get('[cy-name=activity-types]').should('contain', 'This is modified activity type 1');
});
// mae sure the modified activity type exists on the Add activity page
cy.visit('/people')
// delete an activity type
cy.get('[cy-name=add-activity-type-button-for-category-'+item+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=add-type-name]').type('This is activity type 2');
cy.get('[cy-name=add-type-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is activity type 2');
// this gets the first content of the list
cy.get('li.people-list-item.bg-white.pointer').click()
cy.get('[cy-name=add-activity-button]').click();
cy.get('#activity_type_id').should('contain', 'This is modified activity type 1')
cy.get('[cy-name=activity-types-'+item+']').invoke('attr', 'cy-items').then((items) => {
let aitem = _.last(items.split(','));
// create another activity type to delete it right after
cy.visit('/settings/personalization')
cy.get('[cy-name=add-activity-type-button-for-category-5]').click()
cy.get('.sweet-modal-overlay').should('be.visible')
cy.get('[name=add-type-name]').type('This is activity type 2')
cy.get('[cy-name=add-type-button]').click()
cy.get('[cy-name=activity-type-delete-button-15]').click()
cy.get('[cy-name=delete-type-button]').click()
cy.get('[cy-name=activity-types]').should('not.contain', 'This is activity type 2')
cy.get('[cy-name=activity-type-delete-button-'+aitem+']').click();
cy.get('[cy-name=delete-type-button]').click();
cy.get('[cy-name=activity-types]').should('not.contain', 'This is activity type 2');
});
// now delete the activity type category and make sure it also deletes
// the activity type that belonged to it
cy.get('[cy-name=activity-type-category-delete-button-5]').click()
cy.get('[cy-name=delete-category-button]').click()
cy.get('[cy-name=activity-types]').should('not.contain', 'This is still an activity type category')
cy.get('[cy-name=activity-types]').should('not.contain', 'This is modified activity type 1')
})
})
// now delete the activity type category and make sure it also deletes
// the activity type that belonged to it
cy.get('[cy-name=activity-type-category-delete-button-'+item+']').click();
cy.get('[cy-name=delete-category-button]').click();
cy.get('[cy-name=activity-types]').should('not.contain', 'This is still an activity type category');
cy.get('[cy-name=activity-types]').should('not.contain', 'This is modified activity type 1');
});
});
it('lets you add an activity type and use it', function () {
cy.login();
cy.visit('/');
// set account as premium
cy.get('body').invoke('attr', 'data-account-id').then(function ($accountId) {
cy.setPremium($accountId);
});
// make sure that going premium removes restrictions
cy.visit('/settings/personalization');
cy.get('[cy-name=activity-type-premium-message]').should('not.be.visible');
cy.get('[cy-name=activity-types]').should('contain', 'played a sport together');
// add an activity type category
cy.get('[cy-name=add-activity-type-category-button]').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=add-category-name]').type('This is an activity type category');
cy.get('[cy-name=add-activity-type-category-save-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is an activity type category');
cy.get('[cy-name=activity-type-categories]').invoke('attr', 'cy-items').then((items) => {
let item = _.last(items.split(','));
// edit an activity type category
cy.get('[cy-name=activity-type-category-edit-button-'+item+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=update-category-name]').clear();
cy.get('[name=update-category-name]').type('This is still an activity type category');
cy.get('[cy-name=update-activity-type-category-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is still an activity type category');
// add an activity type
cy.get('[cy-name=add-activity-type-button-for-category-'+item+']').click();
cy.get('.sweet-modal-overlay').should('be.visible');
cy.get('[name=add-type-name]').type('This is activity type 1');
cy.get('[cy-name=add-type-button]').click();
cy.get('[cy-name=activity-types]').should('contain', 'This is activity type 1');
// make sure the activity type exists on the Add activity page
cy.createContact('John', 'Doe', 'Man');
cy.get('[cy-name=add-activity-button]').click();
cy.get('[cy-name=activities_add_category]').click();
cy.get('[name=activity-type-list]').should('contain', 'This is activity type 1');
});
});
});
+1 -1
View File
@@ -14,4 +14,4 @@
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
};
+21 -12
View File
@@ -1,15 +1,24 @@
Cypress.Commands.add('login', () => {
cy.exec('php artisan setup:frontendtesting -vvv')
cy.visit('/')
cy.get('input[name=email]').type('admin@admin.com')
cy.get('input[name=password]').type('admin')
cy.get('button[type=submit]').click()
cy.url().should('include', '/dashboard')
})
cy.exec('php artisan setup:frontendtestuser').then((result) => {
cy.visit('/_dusk/login/'+result.stdout+'/');
});
});
Cypress.Commands.add('setPremium', (accountId) => {
cy.exec('php artisan account:setpremium ' + accountId)
})
cy.exec('php artisan account:setpremium ' + accountId);
});
Cypress.Commands.add('register', (firstName, lastName, password, email, policy) => {
cy.visit('/register');
cy.get('.alert').should('not.exist');
cy.get('input[name=email]').type(email);
cy.get('input[name=first_name]').type(firstName);
cy.get('input[name=last_name]').type(lastName);
cy.get('input[name=password]').type(password);
cy.get('input[name=password_confirmation]').type(password);
if (policy) {
cy.get('input[name=policy]').click();
}
cy.get('button[type=submit]').click();
});
+25 -20
View File
@@ -1,29 +1,34 @@
Cypress.Commands.add('createContact', (firstname, lastname, gender, action = 'save') => {
cy.visit('/people')
cy.get('#button-add-contact').click()
cy.visit('/people');
cy.get('#button-add-contact').click();
cy.get('input[name=first_name]').type(firstname)
cy.get('input[name=last_name]').type(lastname)
cy.get('select[name=gender]').select(gender)
cy.get('input[name=first_name]').type(firstname);
cy.get('input[name=last_name]').type(lastname);
cy.get('select[name=gender]').select(gender);
cy.get('button[name=' + action + ']').click()
})
cy.get('button[name=' + action + ']').click();
});
Cypress.Commands.add('createActivity', () => {
cy.visit('/people')
cy.visit('/people');
// this gets the first content of the list
cy.get('li.people-list-item.bg-white.pointer').click()
// this gets the first content of the list
cy.get('tr.clickable.people-list-item.bg-white.pointer').click();
cy.get('[cy-name=add-activity-button]').should('be.visible')
cy.get('[cy-name=add-activity-button]').click()
cy.url().should('include', '/activities/add/h:')
cy.get('[cy-name=add-activity-button]').should('be.visible');
cy.get('[cy-name=add-activity-button]').click();
//cy.url().should('include', '/activities/add/h:');
cy.get('[name=summary]').type('This is a summary')
cy.get('[cy-name=save-activity-button]').click()
cy.get('[name=summary]').type('This is a summary');
cy.get('[cy-name=save-activity-button]').click();
cy.url().should('include', '/people/h:')
cy.get('[cy-name=activities-blank-state]').should('not.be.visible')
cy.get('[cy-name=activity-body-1]').should('exist')
cy.get('[cy-name=activity-body-1]').should('contain', 'This is a summary')
})
cy.url().should('include', '/people/h:');
cy.get('[cy-name=activities-blank-state]').should('not.be.visible');
cy.get('[cy-name=activities-body]').should('be.visible').then((activities) => {
let item = activities[0].getAttribute('cy-items');
cy.get('[cy-name=activity-body-'+item+']').should('exist');
cy.get('[cy-name=activity-body-'+item+']').should('contain', 'This is a summary');
});
});
+3 -3
View File
@@ -14,9 +14,9 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
import './helpers/app'
import './helpers/contacts'
import './commands';
import './helpers/app';
import './helpers/contacts';
// Alternatively you can use CommonJS syntax:
// require('./commands')
+115 -51
View File
@@ -2119,6 +2119,16 @@ cli-spinner@0.2.10:
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
integrity sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==
cli-table3@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202"
integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==
dependencies:
object-assign "^4.1.0"
string-width "^2.1.1"
optionalDependencies:
colors "^1.1.2"
cli-truncate@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
@@ -2242,6 +2252,11 @@ color@^3.0.0:
color-convert "^1.9.1"
color-string "^1.5.2"
colors@^1.1.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@@ -2718,10 +2733,10 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
cypress@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.1.0.tgz#295f115d2e8a08fff2760ab49d94d876f5877aee"
integrity sha512-FFV8pS9iuriSX4M9rna6awJUhiqozZD1D5z5BprCUJoho1ctbcgpkEUIUnqxli2OwjQqVz07egO+iqoGL+tw7g==
cypress@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.2.0.tgz#45673fb648b1a77b9a78d73e58b89ed05212d243"
integrity sha512-8LdreL91S/QiTCLYLNbIjLL8Ht4fJmu/4HGLxUI20Tc7JSfqEfCmXELrRfuPT0kjosJwJJZacdSji9XSRkPKUw==
dependencies:
"@cypress/listr-verbose-renderer" "0.4.1"
"@cypress/xvfb" "1.2.4"
@@ -2731,6 +2746,7 @@ cypress@4.1.0:
cachedir "2.3.0"
chalk "2.4.2"
check-more-types "2.24.0"
cli-table3 "0.5.1"
commander "4.1.0"
common-tags "1.8.0"
debug "4.1.1"
@@ -2746,12 +2762,12 @@ cypress@4.1.0:
listr "0.14.3"
lodash "4.17.15"
log-symbols "3.0.0"
minimist "1.2.0"
minimist "1.2.2"
moment "2.24.0"
ospath "1.2.2"
pretty-bytes "5.3.0"
ramda "0.26.1"
request "2.88.0"
request cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16
request-progress "3.0.0"
supports-color "7.1.0"
tmp "0.1.0"
@@ -3223,7 +3239,7 @@ error-stack-parser@^2.0.0:
dependencies:
stackframe "^1.1.0"
es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1:
es-abstract@^1.17.0-next.0:
version "1.17.0-next.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172"
integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw==
@@ -3240,6 +3256,23 @@ es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1:
string.prototype.trimleft "^2.1.0"
string.prototype.trimright "^2.1.0"
es-abstract@^1.17.0-next.1:
version "1.17.4"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184"
integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==
dependencies:
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.1"
is-callable "^1.1.5"
is-regex "^1.0.5"
object-inspect "^1.7.0"
object-keys "^1.1.1"
object.assign "^4.1.0"
string.prototype.trimleft "^2.1.1"
string.prototype.trimright "^2.1.1"
es-to-primitive@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@@ -3338,6 +3371,13 @@ eslint-module-utils@^2.4.1:
debug "^2.6.9"
pkg-dir "^2.0.0"
eslint-plugin-cypress@^2.7.0:
version "2.10.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.10.3.tgz#82eba7e014954149d590402eecd0d4e147cc7f14"
integrity sha512-CvFeoCquShfO8gHNIKA1VpUTz78WtknMebLemBd1lRbcmJNjwpqCqpQYUG/XVja8GjdX/e2TJXYa+EUBxehtUg==
dependencies:
globals "^11.12.0"
eslint-plugin-es@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b"
@@ -3732,6 +3772,11 @@ extsprintf@^1.2.0:
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
faker@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f"
integrity sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
@@ -4264,7 +4309,7 @@ global-prefix@^3.0.0:
kind-of "^6.0.2"
which "^1.3.1"
globals@^11.1.0:
globals@^11.1.0, globals@^11.12.0:
version "11.12.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
@@ -4363,7 +4408,7 @@ har-schema@^2.0.0:
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.0:
har-validator@~5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
@@ -4948,10 +4993,10 @@ is-buffer@~2.0.3:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623"
integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==
is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
is-callable@^1.1.4, is-callable@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
is-ci@2.0.0:
version "2.0.0"
@@ -4994,9 +5039,9 @@ is-data-descriptor@^1.0.0:
kind-of "^6.0.0"
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==
is-descriptor@^0.1.0:
version "0.1.6"
@@ -5154,7 +5199,7 @@ is-redirect@^1.0.0:
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
is-regex@^1.0.4:
is-regex@^1.0.4, is-regex@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
@@ -5958,17 +6003,17 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@1.2.0, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minimist@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.2.tgz#b00a00230a1108c48c169e69a291aafda3aacd63"
integrity sha512-rIqbOrKb8GJmx/5bc2M0QchhUouMXSpd1RTclXsB41JdL+VtnojfaJR+h7F9k18/4kHUsBFgk80Uk+q569vjPA==
minimist@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de"
integrity sha1-md9lelJXTCHJBXSX33QnkLK0wN4=
minimist@^1.2.5:
minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@@ -6582,7 +6627,14 @@ p-limit@^1.1.0:
dependencies:
p-try "^1.0.0"
p-limit@^2.0.0, p-limit@^2.2.0:
p-limit@^2.0.0:
version "2.2.2"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e"
integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==
dependencies:
p-try "^2.0.0"
p-limit@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
@@ -6852,7 +6904,12 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
picomatch@^2.0.4, picomatch@^2.0.7:
picomatch@^2.0.4:
version "2.2.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a"
integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==
picomatch@^2.0.7:
version "2.1.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
@@ -7396,10 +7453,10 @@ pseudomap@^1.0.2:
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
psl@^1.1.24:
version "1.4.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2"
integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==
psl@^1.1.28:
version "1.7.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
public-encrypt@^4.0.0:
version "4.0.3"
@@ -7443,12 +7500,12 @@ punycode@1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@^1.2.4, punycode@^1.4.1:
punycode@^1.2.4:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0:
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@@ -7785,10 +7842,9 @@ request-progress@3.0.0:
dependencies:
throttleit "^1.0.0"
request@2.88.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
request@cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16:
version "2.88.1"
resolved "https://codeload.github.com/cypress-io/request/tar.gz/b5af0d1fa47eec97ba980cde90a13e69a2afcd16"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
@@ -7797,7 +7853,7 @@ request@2.88.0:
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.0"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
@@ -7807,7 +7863,7 @@ request@2.88.0:
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.4.3"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
@@ -8801,18 +8857,18 @@ string-width@^4.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
string.prototype.trimleft@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634"
integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==
string.prototype.trimleft@^2.1.0, string.prototype.trimleft@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74"
integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
string.prototype.trimright@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58"
integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==
string.prototype.trimright@^2.1.0, string.prototype.trimright@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9"
integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==
dependencies:
define-properties "^1.1.3"
function-bind "^1.1.1"
@@ -9189,13 +9245,13 @@ toml@^3.0.0:
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==
tough-cookie@~2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.24"
punycode "^1.4.1"
psl "^1.1.28"
punycode "^2.1.1"
tree-kill@^1.2.2:
version "1.2.2"
@@ -9960,7 +10016,7 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.2:
yargs-parser@13.1.2, yargs-parser@^13.1.2:
version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
@@ -9976,6 +10032,14 @@ yargs-parser@^11.1.1:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^13.1.0:
version "13.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^15.0.0:
version "15.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08"