Cleaning Test Runs for End to End (E2E) Tests (#12143)
* Added custom seed task * Added a test for the initial login for the intial admin of a forem instance. * Renamed admin login seed data file. * Pulled functions out of main Cypress plugin file and import them now. * Added some comments. * Added a comment about Cypress tasks requiring a return value to be considered successful. * Moved admin_login_setup seed file to spec folder. * Made change requests in regards to rake task. * Fixed reference to SiteConfig * Created the seeder class to be shared for all seed files. * Added a missing param to function comment. * Fixed seeder require in e2e test seed file. * Fixed seeder require in seeds.rb. Why is Rails.root required? * Added an environment guard for not being production in the e2e seed task. * Made seeder require relative. * Trying something for the Elastic Search issue in CI. * Revert "Trying something for the Elastic Search issue in CI." This reverts commit 7cb2a963c8ac1f9242c612a1b9fe8ff814605df6. * Search indices are now removed via bundle exec rake search:destroy * Now rake search:destroy is used in the Cypress task for resetting data as well. * Moved Seeder class to app/lib * Added cypress-rails * Got two flows working with db rollbacks. * Trimmed down the e2e dataset for now. * Added a custom Cypress command to encompass test setup. * removed unused e2e rake task * added some user login/password e2e tests. * Added a note about Cypress not cleaning cookies, so we do for the moment. * Removed code no longer required. * Removed comment in test that is no longer pertinent to the test suite. * Removed data cleaning plugins as cypress rails gem handles it now. * Added @citizen428's recommendation got raising an error if trying to seed production. * Temporarily have paralleziation of e2e tests disabled to figure out cypres-rails/knapsack pro integration. * Doh! Forgot a semi-colon in the Travis config. * Added a comment about not integrating cypress-rails/knapsack pro right now. * Removed knapsack pro npm package for now as we aren't using it. * Reworded comment about cypress-rails/kanpsackpro. * Removed seeding for tags to follow for onboarding in e2e seed data. * Made pree2e script e2e:setup so it only runs explicitly when needed. * Renamed bin/e2e to bin/e2e-ci. * Created a new script for local e2e testing. * Removed RAILS_ENV as it's in the e2e-ci script already. * Fixed an auto corrected command. * Fixed wording in e2e script prompt. * Removed bundle exec rake data_updates:run that I had added. Doesn't appear to be necessary. * Added missing new lines. * Renamed e2e seed file and only use that one now. THere are no others. * Some script cleanup. * Added a check for the E2E environment so as to not pollute system tests. * Now e2e test server cleanup occurs when the server shuts down. * Put puts as this is really just for testing. * Put environment variable in the proper place for runnning bundle exec. * Added a check to only run for E2E tests. * Some bash script formatting. * Removed copy paste irrelevant comments. * Updated e2e server shutdown message. * Now a data-testid attribute is used for finding the user account errors panel. * Made test selectors ignore casing of text. * Removed prod paranoia check in e2e seed file. * Refactored spec to use new cy.loginUser(user) command. * Update app/lib/seeder.rb Co-authored-by: Michael Kohl <citizen428@dev.to> * Fixed flakiness that @aitchiss was experiencing. * Rubocop fix. * Due to a Cypress issue, fixing cookie clearing with another tweak. * Bumped the wait time to 500ms if cookies don't clear. * Added a 'bundle check' to the bin/e2e script as suggested by @katiedavis. * Removed some white space Co-authored-by: Michael Kohl <citizen428@dev.to>
This commit is contained in:
parent
154b185f2d
commit
a7da74b993
26 changed files with 393 additions and 351 deletions
|
|
@ -86,9 +86,7 @@ jobs:
|
|||
- bin/test-console-check
|
||||
- yarn build-storybook
|
||||
- bundle exec rake data_updates:run # required for at least creating the first admin user in e2e tests.
|
||||
- yarn e2e:ci
|
||||
# Dropping and recreating the database for Capybara/rspecs
|
||||
# - curl -XDELETE "${ELASTICSEARCH_URL}/*" # resetting elastic search post e2e tests
|
||||
- bin/e2e-ci
|
||||
|
||||
- stage: Deploy
|
||||
name: Deploy DEV
|
||||
|
|
|
|||
1
Gemfile
1
Gemfile
|
|
@ -141,6 +141,7 @@ group :development, :test do
|
|||
gem "amazing_print", "~> 1.2" # Great Ruby debugging companion: pretty print Ruby objects to visualize their structure
|
||||
gem "bullet", "~> 6.1" # help to kill N+1 queries and unused eager loading
|
||||
gem "capybara", "~> 3.35.1" # Capybara is an integration testing tool for rack based web applications
|
||||
gem "cypress-rails", "~> 0.4.2" # For end to end tests (E2E)
|
||||
gem "dotenv-rails", "~> 2.7.6" # For loading ENV variables locally
|
||||
gem "faker", "~> 2.15" # A library for generating fake data such as names, addresses, and phone numbers
|
||||
gem "knapsack_pro", "~> 2.11.0" # Help parallelize Ruby spec builds
|
||||
|
|
|
|||
|
|
@ -202,6 +202,9 @@ GEM
|
|||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
cypress-rails (0.4.2)
|
||||
puma (>= 3.8.0)
|
||||
railties (>= 5.2.0)
|
||||
dante (0.2.0)
|
||||
database_cleaner (1.8.5)
|
||||
database_cleaner-active_record (1.8.0)
|
||||
|
|
@ -862,6 +865,7 @@ DEPENDENCIES
|
|||
cld (~> 0.8)
|
||||
cloudinary (~> 1.18)
|
||||
counter_culture (~> 2.7)
|
||||
cypress-rails (~> 0.4.2)
|
||||
database_cleaner-active_record (~> 1.8.0)
|
||||
ddtrace (~> 0.45.0)
|
||||
derailed_benchmarks (~> 2.0)
|
||||
|
|
|
|||
47
app/lib/seeder.rb
Normal file
47
app/lib/seeder.rb
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# rubocop:disable Rails/Output
|
||||
|
||||
class Seeder
|
||||
def initialize
|
||||
if Rails.env.production?
|
||||
puts "Can't run seeds in production"
|
||||
|
||||
# rubocop:disable Rails/Exit
|
||||
exit 1
|
||||
# rubocop:enable Rails/Exit
|
||||
end
|
||||
|
||||
@counter = 0
|
||||
end
|
||||
|
||||
# Used when the block is idempotent by itself and needs no further checks.
|
||||
def create(message)
|
||||
@counter += 1
|
||||
puts " #{@counter}. #{message}."
|
||||
yield
|
||||
end
|
||||
|
||||
def create_if_none(klass, count = nil)
|
||||
@counter += 1
|
||||
plural = klass.name.pluralize
|
||||
|
||||
if klass.none?
|
||||
message = ["Creating", count, plural].compact.join(" ")
|
||||
puts " #{@counter}. #{message}."
|
||||
yield
|
||||
else
|
||||
puts " #{@counter}. #{plural} already exist. Skipping."
|
||||
end
|
||||
end
|
||||
|
||||
def create_if_doesnt_exist(klass, attribute_name, attribute_value)
|
||||
record = klass.find_by("#{attribute_name}": attribute_value)
|
||||
if record.nil?
|
||||
puts " #{klass} with #{attribute_name} = #{attribute_value} not found, proceeding..."
|
||||
yield
|
||||
else
|
||||
puts " #{klass} with #{attribute_name} = #{attribute_value} found, skipping."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:enable Rails/Output
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
If you signed up with a social media account, please <a href="<%= new_user_password_path %>">reset the password</a> for your primary email address (<%= current_user.email %>) first.
|
||||
</p>
|
||||
</header>
|
||||
<%= form_with url: user_update_password_path do |f| %>
|
||||
<%= form_with(url: user_update_password_path, data: { testid: "update-password-form" }) do |f| %>
|
||||
<div class="crayons-field mb-4">
|
||||
<%= f.label :current_password, class: "crayons-field__label" %>
|
||||
<%= f.password_field :current_password, class: "crayons-textfield", autocomplete: "off" %>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="crayons-card crayons-card--secondary crayons-notice crayons-notice--danger">
|
||||
<div class="crayons-card crayons-card--secondary crayons-notice crayons-notice--danger" data-testid="account-errors-panel">
|
||||
<div class="crayons-card__header">
|
||||
<h3 class="crayons-card__headline">
|
||||
<%= pluralize(errors.size, "error") %> <%= title_suffix %>:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="crayons-card min-w-0 text-padding">
|
||||
<h2 class="crayons-title mb-4"> Destroy your account</h2>
|
||||
<div class="settings-form">
|
||||
<%= form_tag user_full_delete_path, method: :delete, autocomplete: "off", id: "delete__account", class: 'flex flex-col gap-4 mb-4' do %>
|
||||
<%= form_tag user_full_delete_path, method: :delete, autocomplete: "off", id: "delete__account", class: "flex flex-col gap-4 mb-4" do %>
|
||||
Deleting your account will:
|
||||
<ul class="my-0 ml-6 list-disc">
|
||||
<li>delete your profile, along with your Twitter and/or GitHub associations.
|
||||
|
|
|
|||
24
bin/e2e
24
bin/e2e
|
|
@ -1,9 +1,19 @@
|
|||
#!/bin/bash
|
||||
if [ "$KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS" = "" ]; then
|
||||
KNAPSACK_PRO_ENDPOINT=https://api-disabled-for-fork.knapsackpro.com \
|
||||
KNAPSACK_PRO_MAX_REQUEST_RETRIES=0 \
|
||||
KNAPSACK_PRO_TEST_SUITE_TOKEN_CYPRESS=disabled-for-fork \
|
||||
npx cypress run # run without parallelization
|
||||
else
|
||||
npx knapsack-pro-cypress # parallelization is available
|
||||
printf "Doing a quick bundle check to make sure gems are all up to date.\n\n"
|
||||
bundle check
|
||||
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "Unable to launch end to end tests. Ensure that all your gems are installed and up to date."
|
||||
exit;
|
||||
fi
|
||||
|
||||
printf "\n"
|
||||
|
||||
read -p "Do you need to set up your end to end (E2E) testing database? Answer yes if this is your first time running E2E tests on your local machine or you need to recreate your E2E test database. (y/n) " -n 1 -r
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
printf "\n\nSetting up the E2E database before running E2E tests...\n\n"
|
||||
RAILS_ENV=test E2E=true bin/e2e-setup
|
||||
fi
|
||||
|
||||
CYPRESS_RAILS_CYPRESS_OPTS="--config-file cypress.dev.json" RAILS_ENV=test E2E=true bundle exec rake cypress:open
|
||||
|
|
|
|||
4
bin/e2e-ci
Executable file
4
bin/e2e-ci
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
# As discussed in the engineering roundtable 2021/01/25, we will revisit cypress-rails knapsack pro integration
|
||||
# for re-enabling parallelization of e2e tests later.
|
||||
RAILS_ENV=test E2E=true bundle exec rake cypress:run
|
||||
9
bin/e2e-setup
Executable file
9
bin/e2e-setup
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
if [ -z "$E2E" ]; then
|
||||
echo "Setting up the end to end (E2E) test database did not run. You are not in an E2E test environment.";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
bundle exec rails db:drop;
|
||||
bundle exec rails db:create;
|
||||
bundle exec rails db:schema:load;
|
||||
bundle exec rails assets:precompile;
|
||||
30
config/initializers/cypress_rails.rb
Normal file
30
config/initializers/cypress_rails.rb
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# We want to check not only if we are in the test environment, but also if we are
|
||||
# running E2E tests. Otherwise this will run when system tests run.
|
||||
return unless Rails.env.test? && ENV["E2E"].present?
|
||||
|
||||
# rubocop:disable Rails/Output
|
||||
|
||||
CypressRails.hooks.before_server_start do
|
||||
# Called once, before either the transaction or the server is started
|
||||
puts "Starting up server for end to end tests."
|
||||
Rails.application.load_tasks
|
||||
Rake::Task["db:seed:e2e"].invoke
|
||||
end
|
||||
|
||||
CypressRails.hooks.after_transaction_start do
|
||||
# Called after the transaction is started (at launch and after each reset)
|
||||
end
|
||||
|
||||
CypressRails.hooks.after_state_reset do
|
||||
# Triggered after `/cypress_rails_reset_state` is called
|
||||
end
|
||||
|
||||
CypressRails.hooks.before_server_stop do
|
||||
# Called once, at_exit
|
||||
puts "Cleaning up and stopping server for end to end tests."
|
||||
Rake::Task["search:destroy"].invoke
|
||||
Rake::Task["db:truncate_all"].invoke
|
||||
puts "The end to end test server shutdown gracefully."
|
||||
end
|
||||
|
||||
# rubocop:enable Rails/Output
|
||||
|
|
@ -1,7 +1 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"env": {
|
||||
"FOREM_OWNER_SECRET": "secret",
|
||||
"ELASTICSEARCH_URL": "http://localhost:9200"
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
{
|
||||
"baseUrl": "http://localhost:3000"
|
||||
"screenshotsFolder": "tmp/cypress_screenshots",
|
||||
"trashAssetsBeforeRuns": false,
|
||||
"videosFolder": "tmp/cypress_videos"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"name": "Admin McAdmin",
|
||||
"email": "admin@forem.local",
|
||||
"username": "Admin_McAdmin",
|
||||
"password": "password"
|
||||
}
|
||||
4
cypress/fixtures/users/changePasswordUser.json
Normal file
4
cypress/fixtures/users/changePasswordUser.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"email": "change-password-user@forem.com",
|
||||
"password": "password"
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// Note if you are running these tests locallly, this test will fail
|
||||
// if the first admin has already gone through the onboarding process.
|
||||
|
||||
describe('Initial admin signup', () => {
|
||||
beforeEach(() => {
|
||||
cy.task('resetData');
|
||||
});
|
||||
|
||||
it('should sign up the initial Forem instance administrator', () => {
|
||||
// This is the happy path.
|
||||
cy.fixture('logins/initialAdmin.json').as('admin');
|
||||
|
||||
cy.log('baseUrl', Cypress.config().baseUrl);
|
||||
|
||||
// Go to home page which redirects to the registration form.
|
||||
cy.visit('/');
|
||||
|
||||
cy.findByTestId('registration-form').as('registrationForm');
|
||||
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/Profile image/i)
|
||||
.attachFile('images/admin-image.png');
|
||||
|
||||
cy.get('@admin').then((admin) => {
|
||||
// Enter credentials for the initial administrator user
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/^Name$/i)
|
||||
.type(admin.name);
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/Username/i)
|
||||
.type(admin.username);
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/^Email$/i)
|
||||
.type(admin.email);
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText('Password')
|
||||
.type(admin.password);
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/^Password Confirmation$/i)
|
||||
.type(admin.password);
|
||||
cy.get('@registrationForm')
|
||||
.findByLabelText(/New Forem Secret/i)
|
||||
.type(Cypress.env('FOREM_OWNER_SECRET'));
|
||||
|
||||
// Submit the form
|
||||
cy.get('@registrationForm')
|
||||
.findByText(/^Sign up$/)
|
||||
.click();
|
||||
cy.log('Submitting signup form');
|
||||
|
||||
// The initial administrator user was create and is redirected to the confirm email screen.
|
||||
cy.url().should(
|
||||
'eq',
|
||||
Cypress.config().baseUrl +
|
||||
'/confirm-email?email=' +
|
||||
encodeURIComponent(admin.email),
|
||||
);
|
||||
|
||||
cy.findByTestId('resend-confirmation-form').as('confirmationForm');
|
||||
cy.get('@confirmationForm')
|
||||
.findByLabelText(/^Confirmation email address$/i)
|
||||
.should('have.value', admin.email);
|
||||
cy.get('@confirmationForm').findByText(
|
||||
/^Resend confirmation instructions$/i,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
77
cypress/integration/loginFlows/userChangePassword.spec.js
Normal file
77
cypress/integration/loginFlows/userChangePassword.spec.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
describe('User Change Password', () => {
|
||||
beforeEach(() => {
|
||||
cy.testSetup();
|
||||
cy.fixture('users/changePasswordUser.json').as('user');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.loginUser(user).then(() => {
|
||||
cy.visit('/settings/account');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should change the password of a user', () => {
|
||||
cy.fixture('users/changePasswordUser.json').as('user');
|
||||
|
||||
const newPassword = 'drowssap';
|
||||
|
||||
cy.findByTestId('update-password-form').as('updatePasswordForm');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Current Password$/i)
|
||||
.type(user.password);
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Password$/i)
|
||||
.type(newPassword);
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Confirm new password$/)
|
||||
.type(newPassword);
|
||||
|
||||
// Submit the form
|
||||
cy.get('@updatePasswordForm').findByText('Set New Password').click();
|
||||
|
||||
cy.findByTestId('login-form').as('loginForm');
|
||||
|
||||
cy.get('@loginForm')
|
||||
.findByText(/^Email$/)
|
||||
.type(user.email);
|
||||
cy.get('@loginForm')
|
||||
.findByText(/^Password$/)
|
||||
.type(newPassword);
|
||||
});
|
||||
|
||||
// Submit the form
|
||||
cy.get('@loginForm').findByText('Continue').click();
|
||||
|
||||
const { baseUrl } = Cypress.config();
|
||||
cy.url().should('equal', `${baseUrl}settings/account?signin=true`);
|
||||
});
|
||||
|
||||
it('should give an error if the new password/confirm new password fields do not match when changing the password of a user', () => {
|
||||
cy.fixture('users/changePasswordUser.json').as('user');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.findByTestId('update-password-form').as('updatePasswordForm');
|
||||
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Current Password$/i)
|
||||
.type(user.password);
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Password$/i)
|
||||
.type('some new password that is not the same');
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Confirm new password$/)
|
||||
.type('some other new password that is not the same');
|
||||
});
|
||||
|
||||
// Submit the form
|
||||
cy.get('@updatePasswordForm')
|
||||
.findByText(/^Set New Password$/)
|
||||
.click();
|
||||
|
||||
cy.findByTestId('account-errors-panel').findByText(
|
||||
/^Password doesn't match password confirmation$/,
|
||||
);
|
||||
});
|
||||
});
|
||||
36
cypress/integration/loginFlows/userLogin.spec.js
Normal file
36
cypress/integration/loginFlows/userLogin.spec.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
describe('User Login', () => {
|
||||
beforeEach(() => {
|
||||
cy.testSetup();
|
||||
});
|
||||
|
||||
it('should login a user', () => {
|
||||
cy.fixture('users/changePasswordUser.json').as('user');
|
||||
|
||||
// Go to home page
|
||||
cy.visit('/');
|
||||
|
||||
// Click on the login button in the top header
|
||||
cy.findAllByText('Log in').first().click();
|
||||
|
||||
// Ensure we are redirected to the login page
|
||||
cy.url().should('contains', '/enter');
|
||||
|
||||
cy.findByTestId('login-form').as('loginForm');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.get('@loginForm')
|
||||
.findByText(/^Email$/)
|
||||
.type(user.email);
|
||||
cy.get('@loginForm')
|
||||
.findByText(/^Password$/)
|
||||
.type(user.password);
|
||||
});
|
||||
|
||||
// Submit the form
|
||||
cy.get('@loginForm').findByText('Continue').click();
|
||||
|
||||
// User should be redirected to onboarding
|
||||
const { baseUrl } = Cypress.config();
|
||||
cy.url().should('equal', `${baseUrl}?signin=true`);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
/// <reference types="cypress" />
|
||||
/* eslint-env node */
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
|
|
@ -28,70 +25,5 @@ module.exports = (on, config) => {
|
|||
...process.env,
|
||||
};
|
||||
|
||||
on('task', {
|
||||
async resetData() {
|
||||
const clearSearchIndices = fetch(`${config.env.ELASTICSEARCH_URL}/*`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
|
||||
const truncateDB = new Promise((resolve, reject) => {
|
||||
// Clear the DB for the next test run.
|
||||
const child = spawn('bundle', ['exec', 'rails db:truncate_all']);
|
||||
const errorChunks = [];
|
||||
|
||||
child.stderr.on('data', (chunk) =>
|
||||
errorChunks.push(Buffer.from(chunk)),
|
||||
);
|
||||
|
||||
child.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
child.on('exit', (status, _code) => {
|
||||
if (status !== 0) {
|
||||
const errorMessage = Buffer.concat(errorChunks).toString('UTF-8');
|
||||
|
||||
reject(
|
||||
new Error(
|
||||
`There was an error running "bundle exec rails db:truncate_all". The status was ${status} with the following error:\n${errorMessage}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
resolve(status === 0);
|
||||
});
|
||||
});
|
||||
|
||||
const [clearSearchIndicesResponse, clearedDB = false] = await Promise.all(
|
||||
[
|
||||
clearSearchIndices,
|
||||
truncateDB.catch((error) => {
|
||||
throw new Error(error);
|
||||
}),
|
||||
],
|
||||
);
|
||||
const {
|
||||
acknowledged = false,
|
||||
error,
|
||||
} = await clearSearchIndicesResponse.json();
|
||||
|
||||
if (!acknowledged || error) {
|
||||
throw new Error(
|
||||
`There was an error clearing indices in Elastic Search:\n${
|
||||
error ? JSON.stringify(error, null, '\t') : ''
|
||||
}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!clearedDB) {
|
||||
throw new Error(`The database did not truncate successfully`);
|
||||
}
|
||||
|
||||
// Nothing to do, we're all good.
|
||||
// Cypress tasks require a return value, so returning null.
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
return config;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,3 +23,42 @@
|
|||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
|
||||
/**
|
||||
* Runs necessary test setup to run a clean test.
|
||||
*/
|
||||
Cypress.Commands.add('testSetup', () => {
|
||||
// Required for the moment because of https://github.com/cypress-io/cypress/issues/781
|
||||
cy.clearCookies();
|
||||
|
||||
cy.getCookies().then((cookie) => {
|
||||
if (cookie.length) {
|
||||
// Instead of always waiting, only wait if the cookies aren't
|
||||
// cleared yet and attempt to clear again.
|
||||
cy.wait(500); // eslint-disable-line cypress/no-unnecessary-waiting
|
||||
cy.clearCookies();
|
||||
}
|
||||
});
|
||||
|
||||
cy.request('/cypress_rails_reset_state');
|
||||
});
|
||||
|
||||
/**
|
||||
* Logs in a user with the given email and password.
|
||||
*
|
||||
* @param credentials
|
||||
* @param credentials.email {string} An email address
|
||||
* @param credentials.password {string} A password
|
||||
*
|
||||
* @returns {Cypress.Chainable<Cypress.Response>} A cypress request for signing in a user.
|
||||
*/
|
||||
Cypress.Commands.add('loginUser', ({ email, password }) => {
|
||||
const encodedEmail = encodeURIComponent(email);
|
||||
const encodedPassword = encodeURIComponent(password);
|
||||
|
||||
return cy.request(
|
||||
'POST',
|
||||
'/users/sign_in',
|
||||
`utf8=%E2%9C%93&user%5Bemail%5D=${encodedEmail}&user%5Bpassword%5D=${encodedPassword}&user%5Bremember_me%5D=0&user%5Bremember_me%5D=1&commit=Continue`,
|
||||
);
|
||||
});
|
||||
|
|
|
|||
38
db/seeds.rb
38
db/seeds.rb
|
|
@ -2,43 +2,9 @@
|
|||
|
||||
return if Rails.env.production?
|
||||
|
||||
# NOTE: when adding new data, please use this class to ensure the seed tasks
|
||||
# NOTE: when adding new data, please use the Seeder class to ensure the seed tasks
|
||||
# stays idempotent.
|
||||
class Seeder
|
||||
def initialize
|
||||
@counter = 0
|
||||
end
|
||||
|
||||
# Used when the block is idempotent by itself and needs no further checks.
|
||||
def create(message)
|
||||
@counter += 1
|
||||
puts " #{@counter}. #{message}."
|
||||
yield
|
||||
end
|
||||
|
||||
def create_if_none(klass, count = nil)
|
||||
@counter += 1
|
||||
plural = klass.name.pluralize
|
||||
|
||||
if klass.none?
|
||||
message = ["Creating", count, plural].compact.join(" ")
|
||||
puts " #{@counter}. #{message}."
|
||||
yield
|
||||
else
|
||||
puts " #{@counter}. #{plural} already exist. Skipping."
|
||||
end
|
||||
end
|
||||
|
||||
def create_if_doesnt_exist(klass, attribute_name, attribute_value)
|
||||
record = klass.find_by("#{attribute_name}": attribute_value)
|
||||
if record.nil?
|
||||
puts " #{klass} with #{attribute_name} = #{attribute_value} not found, proceeding..."
|
||||
yield
|
||||
else
|
||||
puts " #{klass} with #{attribute_name} = #{attribute_value} found, skipping."
|
||||
end
|
||||
end
|
||||
end
|
||||
require Rails.root.join("app/lib/seeder")
|
||||
|
||||
# we use this to be able to increase the size of the seeded DB at will
|
||||
# eg.: `SEEDS_MULTIPLIER=2 rails db:seed` would double the amount of data
|
||||
|
|
|
|||
14
lib/tasks/e2e_seed.rake
Normal file
14
lib/tasks/e2e_seed.rake
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Thanks to https://stackoverflow.com/questions/19872271/adding-a-custom-seed-file/31815032#31815032
|
||||
SEED_DIR = Rails.root.join("spec/support/seeds/")
|
||||
|
||||
namespace :db do
|
||||
namespace :seed do
|
||||
desc "Seed data for e2e tests"
|
||||
task e2e: :environment do
|
||||
raise "Attempting to seed production environment, aborting!" if Rails.env.production?
|
||||
|
||||
filename = SEED_DIR.join("seeds_e2e.rb")
|
||||
load(filename) if File.exist?(filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -25,10 +25,7 @@
|
|||
"test": "jest app/javascript/ bin/ --coverage",
|
||||
"test:watch": "jest app/javascript/ bin/ --watch",
|
||||
"postcss": "postcss public/assets/*.css -d public/assets 2> postcss_error.log",
|
||||
"e2e": "cypress open --config-file cypress.dev.json",
|
||||
"e2e:runner": "bin/e2e",
|
||||
"e2e:server": "bin/rails s -p 3000 -b 0.0.0.0",
|
||||
"e2e:ci": "start-server-and-test e2e:server http://localhost:3000 e2e:runner"
|
||||
"e2e": "bin/e2e"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
@ -88,7 +85,6 @@
|
|||
},
|
||||
"homepage": "https://github.com/thepracticaldev/dev.to#readme",
|
||||
"devDependencies": {
|
||||
"@knapsack-pro/cypress": "^4.2.1",
|
||||
"@stoplight/spectral": "5.8.0",
|
||||
"@storybook/addon-a11y": "^6.1.15",
|
||||
"@storybook/addon-actions": "^6.1.15",
|
||||
|
|
@ -135,7 +131,6 @@
|
|||
"jsdom": "^16.4.0",
|
||||
"lint-staged": "^10.5.3",
|
||||
"markdown-loader": "^6.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"prettier": "^2.2.1",
|
||||
"redoc-cli": "0.10.2",
|
||||
"sass": "1.32.5",
|
||||
|
|
|
|||
86
spec/support/seeds/seeds_e2e.rb
Normal file
86
spec/support/seeds/seeds_e2e.rb
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
return unless Rails.env.test? && ENV["E2E"].present?
|
||||
|
||||
# NOTE: when adding new data, please use the Seeder class to ensure the seed tasks
|
||||
# stays idempotent.
|
||||
require Rails.root.join("app/lib/seeder")
|
||||
|
||||
seeder = Seeder.new
|
||||
|
||||
##############################################################################
|
||||
# Default development site config if different from production scenario
|
||||
|
||||
SiteConfig.public = true
|
||||
SiteConfig.waiting_on_first_user = false
|
||||
|
||||
seeder.create_if_none(Organization) do
|
||||
3.times do
|
||||
Organization.create!(
|
||||
name: Faker::TvShows::SiliconValley.company,
|
||||
summary: Faker::Company.bs,
|
||||
remote_profile_image_url: logo = Faker::Company.logo,
|
||||
nav_image: logo,
|
||||
url: Faker::Internet.url,
|
||||
slug: "org#{rand(10_000)}",
|
||||
github_username: "org#{rand(10_000)}",
|
||||
twitter_username: "org#{rand(10_000)}",
|
||||
bg_color_hex: Faker::Color.hex_color,
|
||||
text_color_hex: Faker::Color.hex_color,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
# NOTE: @citizen428 For the time being we want all current DEV profile fields.
|
||||
# The CSV import is idempotent by itself, since it uses find_or_create_by.
|
||||
seeder.create("Creating DEV profile fields") do
|
||||
dev_fields_csv = Rails.root.join("lib/data/dev_profile_fields.csv")
|
||||
ProfileFields::ImportFromCsv.call(dev_fields_csv)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(User, "email", "admin@forem.local") do
|
||||
user = User.create!(
|
||||
name: "Admin McAdmin",
|
||||
email: "admin@forem.local",
|
||||
username: "Admin_McAdmin",
|
||||
summary: Faker::Lorem.paragraph_by_chars(number: 199, supplemental: false),
|
||||
profile_image: File.open(Rails.root.join("app/assets/images/#{rand(1..40)}.png")),
|
||||
website_url: Faker::Internet.url,
|
||||
email_comment_notifications: false,
|
||||
email_follower_notifications: false,
|
||||
confirmed_at: Time.current,
|
||||
password: "password",
|
||||
password_confirmation: "password",
|
||||
saw_onboarding: true,
|
||||
checked_code_of_conduct: true,
|
||||
checked_terms_and_conditions: true,
|
||||
)
|
||||
|
||||
user.add_role(:super_admin)
|
||||
user.add_role(:single_resource_admin, Config)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(User, "email", "change-password-user@forem.com") do
|
||||
User.create!(
|
||||
name: "Change Password User",
|
||||
email: "change-password-user@forem.com",
|
||||
username: "changepassworduser",
|
||||
summary: Faker::Lorem.paragraph_by_chars(number: 199, supplemental: false),
|
||||
profile_image: File.open(Rails.root.join("app/assets/images/#{rand(1..40)}.png")),
|
||||
website_url: Faker::Internet.url,
|
||||
email_comment_notifications: false,
|
||||
email_follower_notifications: false,
|
||||
confirmed_at: Time.current,
|
||||
password: "password",
|
||||
password_confirmation: "password",
|
||||
saw_onboarding: true,
|
||||
checked_code_of_conduct: true,
|
||||
checked_terms_and_conditions: true,
|
||||
)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
BIN
vendor/cache/cypress-rails-0.4.2.gem
vendored
Normal file
BIN
vendor/cache/cypress-rails-0.4.2.gem
vendored
Normal file
Binary file not shown.
160
yarn.lock
160
yarn.lock
|
|
@ -1092,15 +1092,6 @@
|
|||
debug "^3.1.0"
|
||||
lodash.once "^4.1.1"
|
||||
|
||||
"@dabh/diagnostics@^2.0.2":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
|
||||
integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
|
||||
dependencies:
|
||||
colorspace "1.1.x"
|
||||
enabled "2.0.x"
|
||||
kuler "^2.0.0"
|
||||
|
||||
"@emotion/babel-utils@^0.6.4":
|
||||
version "0.6.10"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc"
|
||||
|
|
@ -1510,25 +1501,6 @@
|
|||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@knapsack-pro/core@^3.1.1":
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@knapsack-pro/core/-/core-3.1.1.tgz#fe6f8c8c970cf3b80cc5410ae22f66f3c899ccf2"
|
||||
integrity sha512-yn5PrrM7lAXMr+fr44COOvszzy19ZWoKwD9toRQoZICARfaYGXnYxxBEzdoxkOKk3tJTcYyHGNLc7pn94VNmbg==
|
||||
dependencies:
|
||||
axios "0.21.1"
|
||||
axios-retry "^3.1.9"
|
||||
winston "^3.3.3"
|
||||
|
||||
"@knapsack-pro/cypress@^4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@knapsack-pro/cypress/-/cypress-4.2.1.tgz#0eef46caf4c21c7c3fe198d1ef08a5eabdd6e37c"
|
||||
integrity sha512-r2mdSTWj433GtoBwVFyP/bd1AzUxtY4Txr6H0qaUsBqEKWQ/YkEUQTk5mfQbeJeIl0ZbkTSKqQsRDu+VXqR9wg==
|
||||
dependencies:
|
||||
"@knapsack-pro/core" "^3.1.1"
|
||||
glob "^7.1.6"
|
||||
minimist "^1.2.5"
|
||||
uuid "^8.3.1"
|
||||
|
||||
"@mdx-js/loader@^1.6.19":
|
||||
version "1.6.22"
|
||||
resolved "https://registry.yarnpkg.com/@mdx-js/loader/-/loader-1.6.22.tgz#d9e8fe7f8185ff13c9c8639c048b123e30d322c4"
|
||||
|
|
@ -4039,7 +4011,7 @@ async@^2.6.2:
|
|||
dependencies:
|
||||
lodash "^4.17.14"
|
||||
|
||||
async@^3.0.0, async@^3.1.0, async@^3.2.0:
|
||||
async@^3.0.0, async@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
|
||||
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
|
||||
|
|
@ -4106,20 +4078,6 @@ axe-core@^4.0.1, axe-core@^4.0.2:
|
|||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf"
|
||||
integrity sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ==
|
||||
|
||||
axios-retry@^3.1.9:
|
||||
version "3.1.9"
|
||||
resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.1.9.tgz#6c30fc9aeb4519aebaec758b90ef56fa03fe72e8"
|
||||
integrity sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA==
|
||||
dependencies:
|
||||
is-retry-allowed "^1.1.0"
|
||||
|
||||
axios@0.21.1, axios@^0.21.1:
|
||||
version "0.21.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
|
||||
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
axios@^0.18.0:
|
||||
version "0.18.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3"
|
||||
|
|
@ -4128,6 +4086,13 @@ axios@^0.18.0:
|
|||
follow-redirects "1.5.10"
|
||||
is-buffer "^2.0.2"
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
|
||||
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
axobject-query@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||
|
|
@ -6191,14 +6156,6 @@ color-string@^1.4.0, color-string@^1.5.2, color-string@^1.5.4:
|
|||
color-name "^1.0.0"
|
||||
simple-swizzle "^0.2.2"
|
||||
|
||||
color@3.0.x:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
|
||||
integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==
|
||||
dependencies:
|
||||
color-convert "^1.9.1"
|
||||
color-string "^1.5.2"
|
||||
|
||||
color@^0.11.0:
|
||||
version "0.11.4"
|
||||
resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
|
||||
|
|
@ -6237,19 +6194,11 @@ colorette@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
|
||||
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||
|
||||
colors@^1.1.2, colors@^1.2.1:
|
||||
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==
|
||||
|
||||
colorspace@1.1.x:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
|
||||
integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==
|
||||
dependencies:
|
||||
color "3.0.x"
|
||||
text-hex "1.0.x"
|
||||
|
||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
|
|
@ -7736,11 +7685,6 @@ emotion@^9.1.2, emotion@^9.1.3, emotion@^9.2.12:
|
|||
babel-plugin-emotion "^9.2.11"
|
||||
create-emotion "^9.2.12"
|
||||
|
||||
enabled@2.0.x:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
|
||||
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
|
||||
|
||||
encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
|
|
@ -8544,7 +8488,7 @@ fast-memoize@^2.5.1:
|
|||
resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e"
|
||||
integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==
|
||||
|
||||
fast-safe-stringify@^2.0.4, fast-safe-stringify@^2.0.7:
|
||||
fast-safe-stringify@^2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
|
||||
integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
|
||||
|
|
@ -8584,11 +8528,6 @@ fd-slicer@~1.1.0:
|
|||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fecha@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41"
|
||||
integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==
|
||||
|
||||
figgy-pudding@^3.5.1:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
|
||||
|
|
@ -8819,11 +8758,6 @@ flush-write-stream@^1.0.0:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^2.3.6"
|
||||
|
||||
fn.name@1.x.x:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
|
||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||
|
||||
focus-lock@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.8.1.tgz#bb36968abf77a2063fa173cb6c47b12ac8599d33"
|
||||
|
|
@ -10753,11 +10687,6 @@ is-resolvable@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
|
||||
integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==
|
||||
|
||||
is-retry-allowed@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
|
||||
integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
|
||||
|
||||
is-root@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
|
||||
|
|
@ -11706,11 +11635,6 @@ klona@^2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0"
|
||||
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
|
||||
|
||||
kuler@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
|
||||
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
|
||||
|
||||
language-subtag-registry@~0.3.2:
|
||||
version "0.3.21"
|
||||
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a"
|
||||
|
|
@ -12125,17 +12049,6 @@ log-update@^4.0.0:
|
|||
slice-ansi "^4.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
logform@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
|
||||
integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
|
||||
dependencies:
|
||||
colors "^1.2.1"
|
||||
fast-safe-stringify "^2.0.4"
|
||||
fecha "^4.2.0"
|
||||
ms "^2.1.1"
|
||||
triple-beam "^1.3.0"
|
||||
|
||||
loglevel@^1.6.8:
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
|
||||
|
|
@ -12919,7 +12832,7 @@ node-fetch-h2@^2.3.0:
|
|||
dependencies:
|
||||
http2-client "^1.2.5"
|
||||
|
||||
node-fetch@2.6, node-fetch@2.6.1, node-fetch@^2.6.0, node-fetch@^2.6.1:
|
||||
node-fetch@2.6, node-fetch@2.6.1, node-fetch@^2.6.0:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
|
@ -13370,13 +13283,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
|||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
one-time@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
|
||||
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
|
||||
dependencies:
|
||||
fn.name "1.x.x"
|
||||
|
||||
onecolor@^3.0.4:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/onecolor/-/onecolor-3.1.0.tgz#b72522270a49569ac20d244b3cd40fe157fda4d2"
|
||||
|
|
@ -16061,7 +15967,7 @@ read-pkg@^5.2.0:
|
|||
parse-json "^5.0.0"
|
||||
type-fest "^0.6.0"
|
||||
|
||||
"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6:
|
||||
"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
|
|
@ -16084,7 +15990,7 @@ readable-stream@1.1.x:
|
|||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
|
|
@ -17549,11 +17455,6 @@ stable@^0.1.8:
|
|||
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
|
||||
|
||||
stack-trace@0.0.x:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
||||
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
|
||||
|
||||
stack-utils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277"
|
||||
|
|
@ -18213,11 +18114,6 @@ test-exclude@^6.0.0:
|
|||
glob "^7.1.4"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
text-hex@1.0.x:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
|
||||
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
|
||||
|
||||
text-table@0.2, text-table@0.2.0, text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
|
@ -18443,11 +18339,6 @@ trim@0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
|
||||
integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0=
|
||||
|
||||
triple-beam@^1.2.0, triple-beam@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
|
||||
|
||||
trough@^1.0.0:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||
|
|
@ -18991,7 +18882,7 @@ uuid@^3.3.2, uuid@^3.4.0:
|
|||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||
|
||||
uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1:
|
||||
uuid@^8.0.0, uuid@^8.3.0:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
|
@ -19407,29 +19298,6 @@ widest-line@^3.1.0:
|
|||
dependencies:
|
||||
string-width "^4.0.0"
|
||||
|
||||
winston-transport@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
|
||||
integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
|
||||
dependencies:
|
||||
readable-stream "^2.3.7"
|
||||
triple-beam "^1.2.0"
|
||||
|
||||
winston@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
|
||||
integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
|
||||
dependencies:
|
||||
"@dabh/diagnostics" "^2.0.2"
|
||||
async "^3.1.0"
|
||||
is-stream "^2.0.0"
|
||||
logform "^2.2.0"
|
||||
one-time "^1.0.0"
|
||||
readable-stream "^3.4.0"
|
||||
stack-trace "0.0.x"
|
||||
triple-beam "^1.3.0"
|
||||
winston-transport "^4.4.0"
|
||||
|
||||
wolfy87-eventemitter@~5.2.8:
|
||||
version "5.2.9"
|
||||
resolved "https://registry.yarnpkg.com/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz#e879f770b30fbb6512a8afbb330c388591099c2a"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue