Giter Site home page Giter Site logo

trustedlogin-connector's Introduction

TrustedLogin Vendor

WordPress Tests Backwards Compatiblity JavaScript Tests

Installation And Dev (new)

  • Clone
  • Install javascript dependencies
    • yarn
  • Install php dependencies
    • composer install
    • docker run --rm -it --volume "$(pwd)":/app prooph/composer:7.4 install
  • Ensure wp-scripts is installed globally
    • yarn global add @wordpress/scripts

Develop

JS and CSS:

  • Start CSS watcher
    • yarn start:css
  • Start JS watcher only
    • yarn start:js
  • Test changed files
    • yarn test --watch
  • Test all files once
    • yarn test
    • yarn test --ci
  • Lint JS
    • yarn lint

PHP:

  • Test

(old) Installation

This local dev with Docker was built to work with ngrok, which is not what we're doing now.

Do not install in a directory that includes a space in the path, for example, one under "Local Sites". That will cause issues with wp.js.

IMPORTANT: You must use PHP 7.4 and composer 2.2+ when running composer. The wp.js script runs composer in Docker with the right versions.

  • Git clone:
  • Install javascript dependencies
    • yarn
  • Install php dependencies
    • composer install
    • docker run --rm -it --volume "$(pwd)":/app prooph/composer:7.4 install
  • Create env file
    • cp .env.example .env
    • You will need to ask Josh and/ or Zack for values for NGROK_WP_URL, NGROK_USERS,TL_VENDOR_ENCRYTPTION_KEY and NGROK_AUTH_TOKEN.
  • Setup site using wp.js script.

wp.js

It is important that you use the wp.js script to setup the local dev site, which is served via ngork. The e2e tests assume that site is running and was setup using this script. This script should work with Node 14 or later. Josh developed it using Node 16.

  • Configure WordPress Site
    • node wp.js
      • Installs WordPress
      • Creates admin users, as specified in NGROK_USERS env variable
      • Activates plugin
  • Ensure that Docker is running
  • Build plugin for release and ZIP
    • yarn
    • node wp.js zip

Note: if that doesn't work, make sure Docker is running and then run the following instead:

yarn build && npx --yes plugin-machine plugin build --token=notempty && npx --yes plugin-machine plugin zip --token=notempty
  • Activate Plugin
    • node wp.js --activate
  • Reset WordPress
    • node wp.js ---reset
      • Drops the database tables.

The wp.js script uses docker compose.

Working With JavaScript

There is a React app, for the admin page. It is located in /src. We create two different builds from this app:

  1. WordPress-safe JavaScript
    1. Built with `@wordpress/scripts.
    2. We use this for the admin page.
  2. "App Build"
    1. Built with react-scripts.
    2. We use this for the access key login link in webhooks/helpdesks.
    3. This build includes React and ReactDom and is not safe for use in normal WordPress screens.

Commands

  • Build all JavaScript and CSS for production
    • yarn build

JavaScript

  • Build WordPress JavaScript for production
    • yarn build:js
  • Build the "App Build" JavaScript for production
    • yarn build:app
    • This command requires that npx is installed.
    • npx is used to run react-scripts, instead of installing it in this repo and using yarn, in order to avoid potential conflicts with @wordpress/scripts.
  • Start WordPress Javascript watcher and CSS watcher in parallel
    • yarn start
    • This is busted, open two tabs, yarn start:css, yarn start:js
  • Start JS watcher only
    • yarn start:js
  • Test changed files
    • yarn test --watch
  • Test all files once
    • yarn test
    • yarn test --ci
  • Lint JS
    • yarn lint

CSS

  • Build CSS for production
    • yarn build:css
  • Start CSS watcher for development
    • yarn start:css

Tailwind CSS

The file admin/tailwind.css is used, with Tailwind CSS to write CSS for the admin screens. We are using Tailwind 3, with just in time compliation.

When Tailwind does its purge, it is configured to look for classes in PHP or JavaScript files in the admin directory only.

Working With PHP

Autoloader

PHP classes should be located in the "php" directory and follow the PSR-4 standard.

The root namespace is TrustedLoginVendor.

Container

$container = trustedlogin_connector();

TrustedLoginService

Interactions with TrustedLogin are in the TrustedLoginService. You can get this service, using the container, which it needs, like this:

$service = new TrustedLoginService(
    trustedlogin_connector()
);

Tests

Before doing this, you must create a ".env" file in the root of this plugin. You need to set the correct value for TL_VENDOR_ENCRYTPTION_KEY. Its value is saved in Zack and Josh's password managers. It is set as a Github actions environment variable. This is not needed in production.

  • Run WordPress tests
    • composer test
    • See local development instructions for how to run with Docker.
  • Run e2e Tests

The integration tests mock the SASS API. The mock data was generated using encryption keys for Zack's "Test" team. This is different from the "ngrok" team used for e2e tests.

The integration tests rely on the environment variable TL_VENDOR_ENCRYTPTION_KEY:

{
	 /*
     *        private_key: (string) The private key used for encrypt/decrypt.
	 *        public_key: (string) The public key used for encrypt/decrypt.
	 *        sign_public_key: (string) The public key used for signing/verifying.
	 *        sign_private_key: (string) The private key used for signing/verifying.
     */
}

Linter

PHPCS is installed for linting and automatic code fixing. You can also run these commands in Docker, using wp.js.

  • Run linter and autofix

    • composer fixes
    • node wp.js fixes
  • Run linter to identify issues.

    • compose sniffs
    • node wp.js sniffs
  • Check backwards compat

    • compose compat
    • node wp.js compat

Local Development Environment

A docker-compose-based local development environment is provided.

Starting & WPCLI

  • Start server
    • docker-compose up -d
    • If you get errors about port already being allocated, you can either:
      • Kill all containers and try again: docker kill $(docker ps -q) && docker-compose up -d
      • Change the port in docker-compose.yml.
  • Access Site
  • Run WP CLI command:
    • docker-compose run wpcli wp user create admin [email protected] --role=admin user_pass=pass
  • Because the constantsWP_DEBUG and TRUSTEDLOGIN_DEBUG are set to true, errors will be logged to ./trustedlogin.log.
    • Constants are set in docker-compose.yml, in services.wordpress.environment, under WORDPRESS_CONFIG_EXTRA.
    • I'm not sure where this is documented, but it works. This Stackoverflow discussion is helpful.

PHPUnit

There is a special phpunit container for running WordPress tests, with WordPress and MySQL configured.

  • Enter container
    • docker-compose run phpunit
  • Test
    • composer test:wordpress
  • Run tests once
    • **docker-compose run phpunit phpunit --config=phpunit-integration.xml

If you see prompt Do you trust "dealerdirect/phpcodesniffer-composer-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] y you should answer "y". This is fine.

ngrok

The WordPress site will also be on the internets at https://trustedlogin.ngrok.io/. This requires setting the variable NGROK_AUTH_TOKEN in the .env file.

Find the auth token in the ngrok dashboard, while logged in to the TrustedLogin account. Ask Zack for access if needed.

The ngrok container has a UI for inspecting ngrok requests. It can be accessed at http://localhost:4551/.

End-To-End Testing

We use cypress for end to end testing (e2e) the vendor plugin, and the e2e client. These tests use the production eCommerce app and Vault. These tests use an "ngrok" team. Zack can add and remove people from that team.

The e2e client plugin is installed at https://e2e.trustedlogin.dev/. The e2e tests in that plugin will use that site to grant access to the "ngrok" team. We can get the accessKey from that HTTP request's response. The ngrok endpoint will be serving a WordPress site using whatever version of this plugin is being tested, served at the ngrok endpoint.

Then the tests will log into the vendor site and attempt to use the plugin's setting screen to login to the client site, using the access key.

e2e Test Environment Variables

  • CLIENT_WP_URL
    • URL Of client site:
    • CLIENT_WP_URL=https://e2e.trustedlogin.dev/
  • CLIENT_WP_PASSWORD
    • Password of user on client site that e2e tests login as.
  • CLIENT_WP_USER
    • Username of cf user on client site that e2e tests login as.
    • CLIENT_WP_USER=githubactions
  • NGROK_AUTH_TOKEN
  • NGROK_WP_URL
    • NGROK_WP_URL=https://trustedlogin.ngrok.io
    • ngrok URL for docker compose site.
    • In CI, this value should be https://trustedlogin-ci.ngrok.io

Updating and Troubleshooting Tests

When working on this project, you may occasionally encounter failing tests or need to add new tests for new features. Here are some steps to guide you through this process.

When a Test Fails

  1. Run the test: The easiest way to work on test and ensuring you code is building is to run yarn test --watch .
  2. Understand the test: Look at the test that is failing and understand what it is testing and what the expected behavior is.
    1. You are going to see an error like this:
        ["Warning: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.%s", "
    
       1 | import React from "react";
       2 |
     > 3 | export const SelectFieldArea = ({ id, label, children, htmlFor }) => (
         |                                   ^
       4 |   <div className="">
       5 |     <label
       6 |       htmlFor={htmlFor ? htmlFor : id}
    
       at SelectFieldArea (src/components/teams/fields.js:3:35)
       at SelectField (src/components/teams/fields.js:39:31)
       at HelpDeskSelect (src/components/teams/EditTeam.js:14:34)
       at ViewProvider (src/hooks/useView.js:12:3)
       at SettingsProvider (src/hooks/useSettings.js:267:3)
       at TestProvider (src/components/TestProvider.js:33:3)
           at Provider"]
    
    1. This tells you whats wrong and includes the stack trace where it is happening.
  3. Investigate the failure: Look at the error message and any stack traces that are provided. This information is usually quite helpful in pinpointing the issue.
  4. Fix the code: Update the code to fix the test. This could mean fixing a bug in the implementation or updating the implementation to match a new feature requirement.
  5. Run the test again: If running in watch mode the test will run automatically, otherwise after fixing the code, run the test again to verify that it now passes.

Adding New Tests

  1. Understand the requirement: Before writing the test, you should fully understand the feature you are testing and what the expected behavior is. The previous example is a test for handling the default value.
  2. Write the test: Using the Jest framework, write a test that checks whether the feature behaves as expected.
    1. The following example is a new test to verify how the application would work when the value has changed.
      import { render, fireEvent } from "@testing-library/react";
      
      it("Updates on change", () => {
        const handleChange = jest.fn();
        
        const { getByLabelText } = render(
          <HelpDeskSelect value={"helpscout"} options={options} onChange={handleChange} />,
          {
            wrapper: Provider,
          }
        );
        
        const select = getByLabelText(teamFields.helpdesk.label);
        fireEvent.change(select, { target: { value: 'new value' } });
        expect(handleChange).toBeCalledWith('new value');
      });
    
    1. This test renders the component with a default value and then simulates a change event. It then verifies that the onChange handler was called with the new value.
  3. Run the test: Run the test to ensure it passes and the feature is working as expected.

Updating Snapshot Tests

Sometimes, a test might fail because of changes in the component structure or design, even though the component's functionality hasn't changed. If you verify that the changes are expected and not the result of a bug, you'll need to update the snapshot that Jest uses to compare in future test runs.

Here's how you update Jest snapshots:

  1. Run the following command in your terminal: yarn test -- -u.
  2. Jest will automatically update the snapshots and re-run the tests.
  3. Check the snapshot changes in your Git diff to ensure that all changes are as expected and intentional.
  4. If everything looks good, commit the updated snapshot files.

Remember, updating snapshots should be done cautiously. Ensure that you've fully reviewed and understand any snapshot changes before committing them.

Never update a snapshot if you see an unexpected change, as this might be an indication of a regression or bug in your code.

trustedlogin-connector's People

Contributors

shelob9 avatar zackkatz avatar mgratch avatar mrcasual avatar danieliser avatar

Watchers

 avatar  avatar  avatar Nikhil Vimal avatar

trustedlogin-connector's Issues

End to End tests e2e

Add e2e tests for:

  • Access grant request #56
  • Access grant request with EDD SL license verification.
  • Access key login #56
  • Access key login, invalid accessKey #56
  • Access key login with EDD SL license verification.
  • Access key login, invalid accessKey #56
  • Webhook
  • Webhook, invalid signature
  • Webhook with EDD SL license verification.

Probably move EDD tests to a different ticket for later.

Tailwind-based UI

  • The HTML files from the designer: https://i.gravityview.co/3DnVC8+
  • Designers' message:
    Here's the HTML files. I did the custom dropdowns as needed so the developer can just pull any other dropdowns directly from Tailwind UI. Also, I'm pretty certain the account dropdown position will need to be handled by the developer as the positioning is iffy with the current markup.

Use same form submit/ window.location redirect flow with Helpscout as form

  • In Help Scout widget HTML output, encrypt access key
  • Add Webhook class constant for the encrypted access key
  • Decrypt the access key in the Access Key Login form before pre-filling
  • In HS widget HTML, fix the redirect URL
  • On click of HS widget, load access key form, with values prefilled, and then trigger submit/ redirect flow
  • Merge that working
  • Make it so when returning from HS, do not see wp-admin
    • Echo React app template and exist at admin_init
    • Use webpack manifest to know CSS/JS files to include.

Improve CI for cypress.io

The way I'm running cypress in Docker compose works locally, but not in CI because I have a separate package.json for cypress and that's a hack. I can probably fix that issue in CI -- I'm papering over it locally. But, using their Github integration might be a better idea than what I'm doing.

Only use integrations that are enabled

Once #40 is merged, there will be saved enabled/ disabled status for integrations. Plugin should only expose webhooks for enabled integrations. Now it does one Helpscout webhook, per team.

Hide admin notices & nags

We want to not have the .update-nag affect the layout. But we could also hide all .notice and .notice-* boxes just in case…


Use translation functions in UI

  • JS @wordpress/i18n __ package is installed. It's not well used.
  • It's not setup.
  • Text domain is defined but not registered.

Rename admin/trusted-login-access

Hey, I don't want to break any admin pages so could you please make sure to rename admin/trusted-login-access to admin/trustedlogin-access?

Thanks 👍

Submenus

MENUS: Teams, settings, access key login, getting started, see new design in Slack.
image-2

Do something with errors

Access key and reset links can result in wp_errors, they get var_dumped to screen now, which is less than ideal. Related: #35

https://github.com/trustedlogin/vendor/blob/main/admin/trustedlogin-settings/init.php#L54-L58

Show login stats in TeamsList

This HTML was removed from TeamsList in
e3cace3

<div className="flex items-center justify-self-end">
                          <p className="text-sm mr-4 sm:w-18">
                            148 <span className="text-gray-500">logins</span>
                          </p>
                          <div className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-green-100 text-green-600">
                            <svg
                              className="-ml-1 mr-0.5 flex-shrink-0 self-center h-4 w-4 text-green-600"
                              xmlns="http://www.w3.org/2000/svg"
                              viewBox="0 0 20 20"
                              fill="currentColor"
                              aria-hidden="true">
                              <path
                                fillRule="evenodd"
                                d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
                                clipRule="evenodd"
                              />
                            </svg>
                            <span className="sr-only">Increased by</span>
                            5%
                          </div>
                        </div>

Automate e2e Tests In CI with Instawp and Checkly

Plan

  1. When a PR is opened:
  2. When PR is updated
    • Redpoly or refresh InstaWP site
    • Trigger tests with Checkly
  3. When PR is closed
    • Delete site in InstaWP

e2e-tl-vendor drawio

Questions

  1. Do we redeploy/ reset the InstaWP site or delete it and remake it?
  2. How to delete an InstaWP site?
  3. Why did my last run of the InstaWP github action fail?

Fatal error when testing on PHP 7.3.5

[17-Feb-2022 15:51:02 UTC] PHP Fatal error:  Cannot declare class ParagonIE_Sodium_Compat, because the name is already in use in /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/paragonie/sodium_compat/src/Compat.php on line 28
[17-Feb-2022 15:51:02 UTC] PHP Stack trace:
[17-Feb-2022 15:51:02 UTC] PHP   1. {main}() /Users/zackkatz/Local Sites/dev/app/public/wp-admin/admin.php:0
[17-Feb-2022 15:51:02 UTC] PHP   2. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-admin/admin.php:34
[17-Feb-2022 15:51:02 UTC] PHP   3. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-load.php:50
[17-Feb-2022 15:51:02 UTC] PHP   4. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-config.php:118
[17-Feb-2022 15:51:02 UTC] PHP   5. include_once() /Users/zackkatz/Local Sites/dev/app/public/wp-settings.php:409
[17-Feb-2022 15:51:02 UTC] PHP   6. include_once() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/trustedlogin-vendor.php:40
[17-Feb-2022 15:51:02 UTC] PHP   7. ComposerAutoloaderInit77f92acd995dc3a5e1fd5b06b39847c7::getLoader() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/autoload.php:7
[17-Feb-2022 15:51:02 UTC] PHP   8. composerRequire77f92acd995dc3a5e1fd5b06b39847c7() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/composer/autoload_real.php:61
[17-Feb-2022 15:51:02 UTC] PHP   9. require() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/composer/autoload_real.php:71
[17-Feb-2022 15:51:02 UTC] PHP Notice:  is_embed was called <strong>incorrectly</strong>. Conditional query tags do not work before the query is run. Before then, they always return false. Please see <a href="https://wordpress.org/support/article/debugging-in-wordpress/">Debugging in WordPress</a> for more information. (This message was added in version 3.1.0.) in /Users/zackkatz/Local Sites/dev/app/public/wp-includes/functions.php on line 5663
[17-Feb-2022 15:51:02 UTC] PHP Stack trace:
[17-Feb-2022 15:51:02 UTC] PHP   1. {main}() /Users/zackkatz/Local Sites/dev/app/public/wp-admin/admin.php:0
[17-Feb-2022 15:51:02 UTC] PHP   2. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-admin/admin.php:34
[17-Feb-2022 15:51:02 UTC] PHP   3. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-load.php:50
[17-Feb-2022 15:51:02 UTC] PHP   4. require_once() /Users/zackkatz/Local Sites/dev/app/public/wp-config.php:118
[17-Feb-2022 15:51:02 UTC] PHP   5. include_once() /Users/zackkatz/Local Sites/dev/app/public/wp-settings.php:409
[17-Feb-2022 15:51:02 UTC] PHP   6. include_once() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/trustedlogin-vendor.php:40
[17-Feb-2022 15:51:02 UTC] PHP   7. ComposerAutoloaderInit77f92acd995dc3a5e1fd5b06b39847c7::getLoader() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/autoload.php:7
[17-Feb-2022 15:51:02 UTC] PHP   8. composerRequire77f92acd995dc3a5e1fd5b06b39847c7() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/composer/autoload_real.php:61
[17-Feb-2022 15:51:02 UTC] PHP   9. require() /Users/zackkatz/Local Sites/dev/app/public/wp-content/plugins/vendor/vendor/composer/autoload_real.php:71
[17-Feb-2022 15:51:02 UTC] PHP  10. WP_Fatal_Error_Handler->handle() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/class-wp-fatal-error-handler.php:0
[17-Feb-2022 15:51:02 UTC] PHP  11. WP_Fatal_Error_Handler->display_error_template() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/class-wp-fatal-error-handler.php:57
[17-Feb-2022 15:51:02 UTC] PHP  12. WP_Fatal_Error_Handler->display_default_error_template() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/class-wp-fatal-error-handler.php:152
[17-Feb-2022 15:51:02 UTC] PHP  13. wp_die() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/class-wp-fatal-error-handler.php:233
[17-Feb-2022 15:51:02 UTC] PHP  14. _default_wp_die_handler() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/functions.php:3599
[17-Feb-2022 15:51:02 UTC] PHP  15. wp_robots() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/functions.php:3675
[17-Feb-2022 15:51:02 UTC] PHP  16. apply_filters() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/robots-template.php:32
[17-Feb-2022 15:51:02 UTC] PHP  17. WP_Hook->apply_filters() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/plugin.php:189
[17-Feb-2022 15:51:02 UTC] PHP  18. wp_robots_noindex_embeds() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/class-wp-hook.php:303
[17-Feb-2022 15:51:02 UTC] PHP  19. is_embed() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/robots-template.php:93
[17-Feb-2022 15:51:02 UTC] PHP  20. _doing_it_wrong() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/query.php:881
[17-Feb-2022 15:51:02 UTC] PHP  21. trigger_error() /Users/zackkatz/Local Sites/dev/app/public/wp-includes/functions.php:5663

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.