add-cms
This commit is contained in:
1 parent
30106e0129
commit
0ae8d7a709
1044 files changed
+321581
No files matched your search
@@ -0,0 +1,83 @@
|
||||
# Cypress Tests Guide
|
||||
|
||||
## Introduction
|
||||
|
||||
[Cypress](https://www.cypress.io/) is a JavaScript End to End Testing Framework that runs in the browser.
|
||||
|
||||
Cypress tests run with a [local version](../dev-test) of the CMS.
|
||||
|
||||
During the setup of a spec file, the relevant `index.html` and `config.yml` are copied from `dev-test/backends/<backend>` to `dev-test`.
|
||||
|
||||
Tests for the `test` backend use mock data generated in `dev-test/backends/test/index.html`.
|
||||
|
||||
Tests for the other backends use previously [recorded data](fixtures) and stub `fetch` [calls](support/commands.js#L52). See more about recording tests data [here](#recording-tests-data).
|
||||
|
||||
## Run Tests Locally
|
||||
|
||||
```bash
|
||||
npm run test:e2e # builds the demo site and runs Cypress in headless mode with mock data
|
||||
```
|
||||
|
||||
## Debug Tests
|
||||
|
||||
```bash
|
||||
npm run develop # starts a local dev server with the demo site
|
||||
npm run test:e2e:exec # runs Cypress in non-headless mode with mock data
|
||||
```
|
||||
|
||||
## Recording Tests Data
|
||||
|
||||
When recording tests, access to the relevant backend API is required, thus one must set up a `.env` file in the root project directory in the following format:
|
||||
|
||||
```bash
|
||||
GITHUB_REPO_OWNER=owner
|
||||
GITHUB_REPO_NAME=repo
|
||||
GITHUB_REPO_TOKEN=tokenWithWritePermissions
|
||||
GITHUB_OPEN_AUTHORING_OWNER=forkOwner
|
||||
GITHUB_OPEN_AUTHORING_TOKEN=tokenWithWritePermissions
|
||||
|
||||
GITLAB_REPO_OWNER=owner
|
||||
GITLAB_REPO_NAME=repo
|
||||
GITLAB_REPO_TOKEN=tokenWithWritePermissions
|
||||
|
||||
BITBUCKET_REPO_OWNER=owner
|
||||
BITBUCKET_REPO_NAME=repo
|
||||
BITBUCKET_OUATH_CONSUMER_KEY=ouathConsumerKey
|
||||
BITBUCKET_OUATH_CONSUMER_SECRET=ouathConsumerSecret
|
||||
|
||||
NETLIFY_API_TOKEN=netlifyApiToken
|
||||
NETLIFY_INSTALLATION_ID=netlifyGitHubInstallationId
|
||||
```
|
||||
|
||||
> The structure of the relevant repo should match the settings in [`config.yml`](../dev-test/backends/<backend>/config.yml#L1)
|
||||
|
||||
To start a recording run the following commands:
|
||||
|
||||
```bash
|
||||
npm run develop # starts a local dev server with the demo site
|
||||
npm run mock:server:start # starts the recording proxy
|
||||
npm run test:e2e:record-fixtures:dev # runs Cypress in non-headless and pass data through the recording proxy
|
||||
npm run mock:server:stop # stops the recording proxy
|
||||
```
|
||||
|
||||
> During the recorded process a clone of the relevant repo will be created under `.temp` and reset between tests.
|
||||
|
||||
Recordings are sanitized from any possible sensitive data and [transformed](plugins/common.js#L34) into an easier to process format.
|
||||
|
||||
To avoid recording all the tests over and over again, a recommended process is to:
|
||||
|
||||
1. Mark the specific test as `only` by changing `it("some test...` to `it.only("some test...` for the relevant test.
|
||||
2. Run the test in recording mode.
|
||||
3. Exit Cypress and stop the proxy.
|
||||
4. Run the test normally (with mock data) to verify the recording works.
|
||||
|
||||
## Debugging Playback Failures
|
||||
|
||||
Most common failures are:
|
||||
|
||||
1. The [recorded data](utils/mock-server.js#L17) is not [transformed](plugins/common.js#L34) properly (e.g. sanitization broke something).
|
||||
2. The [stubbed requests and responses](support/commands.js#L82) are not [matched](support/commands.js#L32) properly (e.g. timestamp changes in request body between recording and playback).
|
||||
|
||||
Dumping all recorded data as is to a file [here](utils/mock-server.js#L24) and adding a `debugger;` statement [here](support/commands.js#L52) is useful to gain insights.
|
||||
|
||||
Also comparing console log messages between recording and playback is very useful (ordering of requests, etc.)
|
||||
@@ -0,0 +1,93 @@
|
||||
import '../../utils/dismiss-local-backup';
|
||||
import {
|
||||
login,
|
||||
createPost,
|
||||
createPostAndExit,
|
||||
updateExistingPostAndExit,
|
||||
exitEditor,
|
||||
goToWorkflow,
|
||||
goToCollections,
|
||||
updateWorkflowStatus,
|
||||
publishWorkflowEntry,
|
||||
assertWorkflowStatusInEditor,
|
||||
assertPublishedEntry,
|
||||
deleteEntryInEditor,
|
||||
assertOnCollectionsPage,
|
||||
assertEntryDeleted,
|
||||
assertWorkflowStatus,
|
||||
updateWorkflowStatusInEditor,
|
||||
} from '../../utils/steps';
|
||||
import { workflowStatus, editorStatus } from '../../utils/constants';
|
||||
|
||||
export default function({ entries, getUser }) {
|
||||
it('successfully loads', () => {
|
||||
login(getUser());
|
||||
});
|
||||
|
||||
it('can create an entry', () => {
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
});
|
||||
|
||||
it('can update an entry', () => {
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
updateExistingPostAndExit(entries[0], entries[1]);
|
||||
});
|
||||
|
||||
it('can publish an editorial workflow entry', () => {
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
goToWorkflow();
|
||||
updateWorkflowStatus(entries[0], workflowStatus.draft, workflowStatus.ready);
|
||||
publishWorkflowEntry(entries[0]);
|
||||
});
|
||||
|
||||
it('can change workflow status', () => {
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
goToWorkflow();
|
||||
updateWorkflowStatus(entries[0], workflowStatus.draft, workflowStatus.review);
|
||||
updateWorkflowStatus(entries[0], workflowStatus.review, workflowStatus.ready);
|
||||
updateWorkflowStatus(entries[0], workflowStatus.ready, workflowStatus.review);
|
||||
updateWorkflowStatus(entries[0], workflowStatus.review, workflowStatus.draft);
|
||||
updateWorkflowStatus(entries[0], workflowStatus.draft, workflowStatus.ready);
|
||||
});
|
||||
|
||||
it('can change status on and publish multiple entries', () => {
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
createPostAndExit(entries[1]);
|
||||
createPostAndExit(entries[2]);
|
||||
goToWorkflow();
|
||||
updateWorkflowStatus(entries[2], workflowStatus.draft, workflowStatus.ready);
|
||||
updateWorkflowStatus(entries[1], workflowStatus.draft, workflowStatus.ready);
|
||||
updateWorkflowStatus(entries[0], workflowStatus.draft, workflowStatus.ready);
|
||||
publishWorkflowEntry(entries[2]);
|
||||
publishWorkflowEntry(entries[1]);
|
||||
publishWorkflowEntry(entries[0]);
|
||||
goToCollections();
|
||||
assertPublishedEntry([entries[2], entries[1], entries[0]]);
|
||||
});
|
||||
|
||||
it('can delete an entry', () => {
|
||||
login(getUser());
|
||||
createPost(entries[0]);
|
||||
deleteEntryInEditor();
|
||||
assertOnCollectionsPage();
|
||||
assertEntryDeleted(entries[0]);
|
||||
});
|
||||
|
||||
it('can update workflow status from within the editor', () => {
|
||||
login(getUser());
|
||||
createPost(entries[0]);
|
||||
assertWorkflowStatusInEditor(editorStatus.draft);
|
||||
updateWorkflowStatusInEditor(editorStatus.review);
|
||||
assertWorkflowStatusInEditor(editorStatus.review);
|
||||
updateWorkflowStatusInEditor(editorStatus.ready);
|
||||
assertWorkflowStatusInEditor(editorStatus.ready);
|
||||
exitEditor();
|
||||
goToWorkflow();
|
||||
assertWorkflowStatus(entries[0], workflowStatus.ready);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import '../../utils/dismiss-local-backup';
|
||||
import {
|
||||
login,
|
||||
createPostAndExit,
|
||||
goToWorkflow,
|
||||
goToCollections,
|
||||
updateWorkflowStatus,
|
||||
publishWorkflowEntry,
|
||||
assertPublishedEntry,
|
||||
} from '../../utils/steps';
|
||||
import { workflowStatus } from '../../utils/constants';
|
||||
|
||||
const versions = ['2.9.7', '2.10.24'];
|
||||
|
||||
export default function({ entries, getUser }) {
|
||||
versions.forEach(version => {
|
||||
it(`migrate from ${version} to latest`, () => {
|
||||
cy.task('switchToVersion', {
|
||||
version,
|
||||
});
|
||||
cy.reload();
|
||||
|
||||
login(getUser());
|
||||
createPostAndExit(entries[0]);
|
||||
createPostAndExit(entries[1]);
|
||||
createPostAndExit(entries[2]);
|
||||
goToWorkflow();
|
||||
updateWorkflowStatus(entries[2], workflowStatus.draft, workflowStatus.ready);
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1500); // older versions of the CMS didn't wait fully for the update to be resolved
|
||||
updateWorkflowStatus(entries[1], workflowStatus.draft, workflowStatus.ready);
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1500); // older versions of the CMS didn't wait fully for the update to be resolved
|
||||
updateWorkflowStatus(entries[0], workflowStatus.draft, workflowStatus.ready);
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1500); // older versions of the CMS didn't wait fully for the update to be resolved
|
||||
|
||||
cy.task('switchToVersion', {
|
||||
version: 'latest',
|
||||
});
|
||||
cy.reload();
|
||||
|
||||
// allow migration code to run for 5 minutes
|
||||
publishWorkflowEntry(entries[2], 5 * 60 * 1000);
|
||||
publishWorkflowEntry(entries[1]);
|
||||
publishWorkflowEntry(entries[0]);
|
||||
goToCollections();
|
||||
assertPublishedEntry([entries[2], entries[1], entries[0]]);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loaded 3 of 1044 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user