Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to manage plugins without using the command line #1824

Merged
merged 3 commits into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/test-plugins.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Tests (Acceptance-Plugins)

on:
push:
branches:
- main
- support/*
pull_request:

jobs:
tests:

strategy:
fail-fast: false # continue other tests if one test in matrix fails
matrix:
node-version: [16.x, 18.x]
os: [macos-latest, windows-latest, ubuntu-latest]

name: Acceptance test kit on Node v${{ matrix.node-version }} (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 25

env:
CYPRESS_CACHE_FOLDER: ~/.cache/Cypress

steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Use Node v${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
cache: 'npm'
node-version: ${{ matrix.node-version }}

- name: Cache Cypress binary
uses: actions/cache@v3
with:
path: ~/.cache/Cypress
key: cypress-${{ runner.os }}-cypress-${{ hashFiles('**/package.json') }}

- run: npm ci

- run: npm run test:acceptance:plugins
env:
CYPRESS_REQUEST_TIMEOUT: 20000
CYPRESS_DEFAULT_COMMAND_TIMEOUT: 40000
CYPRESS_PAGE_LOAD_TIMEOUT: 120000
CYPRESS_RETRIES: 3

- if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: cypress-screenshots-dev-${{ runner.os }}-${{ matrix.node-version }}
path: cypress/screenshots/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### New features

- [#1824: Add feature to manage plugins without using the command line](https://github.com/alphagov/govuk-prototype-kit/pull/1824)

### Fixes

- [#1849: Update dependencies](https://github.com/alphagov/govuk-prototype-kit/pull/1849)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ describe('Management plugins: ', () => {
before(() => {
cy.task('log', 'Visit the manage prototype plugins page')
installPlugin(plugin, version2)
cy.wait(5000)
cy.wait(8000)
waitForApplication(manageTemplatesPagePath)
})

after(() => {
installPlugin(plugin, version1)
cy.wait(5000)
cy.wait(8000)
})

it(`Preview a ${plugin}${version2} template`, () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
const { waitForApplication, installPlugin, getTemplateLink, deleteFile } = require('../../utils')
const { capitalize } = require('lodash')
const path = require('path')
const { showHideAllLinkQuery, assertVisible, assertHidden } = require('../../step-by-step-utils')
const appViews = path.join(Cypress.env('projectFolder'), 'app', 'views')
const managePluginsPagePath = '/manage-prototype/plugins'
const plugin = '@govuk-prototype-kit/step-by-step'
const version1 = '@1.0.0'
const version2 = '@2.1.0'
const pluginName = 'Step By Step'
const pluginPageTemplate = '/templates/step-by-step-navigation.html'
const pluginPageTitle = 'Step by step navigation'
const pluginPagePath = '/step-by-step-navigation'

const cleanup = () => {
deleteFile(path.join(appViews, 'step-by-step-navigation.html'))
// Make sure plugin version 1 is installed
installPlugin(plugin, version1)
cy.wait(8000)
}

const panelProcessingQuery = '[aria-live="polite"] #panel-processing'
const panelCompleteQuery = '[aria-live="polite"] #panel-complete'
const panelErrorQuery = '[aria-live="polite"] #panel-error'

const performPluginAction = (action) => {
cy.task('log', `The ${plugin} plugin should be displayed`)
cy.get('h2')
.should('contains.text', `${capitalize(action)} ${pluginName}`)

cy.get(panelCompleteQuery)
.should('not.be.visible')
cy.get(panelCompleteQuery)
.should('not.be.visible')
cy.get(panelErrorQuery)
.should('not.be.visible')
cy.get(panelProcessingQuery)
.should('be.visible')
.should('contain.text', `${capitalize(action === 'upgrade' ? 'Upgrad' : action)}ing ...`)

cy.get(panelProcessingQuery, { timeout: 20000 })
.should('not.be.visible')
cy.get(panelErrorQuery)
.should('not.be.visible')
cy.get(panelCompleteQuery)
.should('be.visible')
.should('contain.text', `${capitalize(action)} complete`)

cy.get('#instructions-complete a')
.should('contain.text', 'Back to plugins')
.wait(3000)
.click()

cy.get('h1').should('have.text', 'Plugins')
}

const provePluginFunctionalityWorks = () => {
cy.wait(2000)

cy.task('log', `Prove ${pluginName} functionality works`)

cy.visit(pluginPagePath)

// click toggle button and check that all steps details are visible
cy.get(showHideAllLinkQuery).should('contains.text', 'Show all').click()
assertVisible(1)
assertVisible(2)

// click toggle button and check that all steps details are hidden
cy.get(showHideAllLinkQuery).should('contains.text', 'Hide all').click()
assertHidden(1)
assertHidden(2)
}

const provePluginFunctionalityFails = () => {
cy.on('uncaught:exception', (err, runnable) => {
console.log(err)
// returning false here prevents Cypress from
// failing a test when javascript in the browser fails
return false
})

cy.wait(2000)

cy.task('log', `Prove ${pluginName} functionality fails`)

cy.visit(pluginPagePath)

cy.get(showHideAllLinkQuery).should('not.exist')
}

describe('Management plugins: ', () => {
before(() => {
cleanup()
cy.task('log', 'Visit the manage prototype plugins page')
waitForApplication(managePluginsPagePath)
})

after(() => {
cleanup()
})

beforeEach(() => {
cy.wait(4000)
})

it('CSRF Protection on POST action', () => {
const installUrl = `${managePluginsPagePath}/install`
cy.task('log', `Posting to ${installUrl} without csrf protection`)
cy.request({
url: `${managePluginsPagePath}/install`,
method: 'POST',
failOnStatusCode: false,
body: { package: plugin }
}).then(response => {
expect(response.status).to.eq(403)
expect(response.body).to.eq('invalid csrf token')
})
})

it(`Upgrade the ${plugin}${version1} plugin to ${plugin}${version2}`, () => {
cy.task('log', `Upgrade the ${plugin} plugin`)
cy.get(`button[formaction*="/upgrade?package=${encodeURIComponent(plugin)}"]`)
.should('contains.text', 'Upgrade').click()

performPluginAction('upgrade', version2)
})

it(`Create a page using a template from the ${plugin} plugin`, () => {
cy.get('a[href*="/templates"]')
.should('contains.text', 'Templates').click()

cy.get('h2').eq(2).should('contain.text', pluginName)

cy.task('log', `Create a new ${pluginPageTitle} page`)

cy.get(`a[href="${getTemplateLink('install', '@govuk-prototype-kit/step-by-step', pluginPageTemplate)}"]`).click()

// create step-by-step-navigation page
cy.get('.govuk-heading-l')
.should('contains.text', `Create new ${pluginPageTitle} page`)
cy.get('#chosen-url')
.type(pluginPagePath)
cy.get('.govuk-button')
.should('contains.text', 'Create page').click()

provePluginFunctionalityWorks()
})

it(`Uninstall the ${plugin} plugin`, () => {
cy.visit(managePluginsPagePath)
cy.task('log', `Uninstall the ${plugin} plugin`)
cy.get(`button[formaction*="/uninstall?package=${encodeURIComponent(plugin)}"]`)
.should('contains.text', 'Uninstall').click()

performPluginAction('uninstall')

provePluginFunctionalityFails()
})

it(`Install the ${plugin} plugin`, () => {
cy.visit(managePluginsPagePath)
cy.task('log', `Install the ${plugin} plugin`)
cy.get(`button[formaction*="/install?package=${encodeURIComponent(plugin)}"]`)
.should('contains.text', 'Install').click()

performPluginAction('install')

provePluginFunctionalityWorks()
})

describe('Get plugin page directly', () => {
it('Pass when installing a plugin already installed', () => {
cy.task('log', `Simulate refreshing the install ${plugin} plugin confirmation page`)
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(plugin)}`)

cy.get('#plugin-action-button').click()

performPluginAction('install')
})

it('Fail when installing a non existent plugin', () => {
const pkg = 'invalid-prototype-kit-plugin'
const pluginName = 'Invalid Prototype Kit Plugin'
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(pkg)}`)
cy.get('h2')
.should('contains.text', `Install ${pluginName}`)

cy.get('#plugin-action-button').click()

cy.get(panelCompleteQuery)
.should('not.be.visible')
cy.get(panelErrorQuery)
.should('not.be.visible')
cy.get(panelProcessingQuery)
.should('be.visible')
.should('contain.text', 'Installing ...')

cy.get(panelProcessingQuery, { timeout: 40000 })
.should('not.be.visible')
cy.get(panelCompleteQuery)
.should('not.be.visible')
cy.get(panelErrorQuery)
.should('be.visible')

cy.get(`${panelErrorQuery} .govuk-panel__title`)
.should('contain.text', 'There was a problem installing')
cy.get(`${panelErrorQuery} a`)
.should('contain.text', 'Please contact support')
})
})
})
3 changes: 2 additions & 1 deletion govuk-prototype-kit.config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"assets": [
"/lib/assets/images",
"/lib/assets/javascripts/optional"
"/lib/assets/javascripts/optional",
"/lib/assets/javascripts/manage-prototype"
],
"nunjucksPaths": "/lib/nunjucks",
"nunjucksFilters": "/lib/filters/coreFilters",
Expand Down
Loading