Skip to content

Commit

Permalink
Adding plugin page, updating plugin lookup and install/uninstall/update
Browse files Browse the repository at this point in the history
  • Loading branch information
nataliecarey committed Sep 12, 2023
1 parent 86fb72a commit c5119bf
Show file tree
Hide file tree
Showing 45 changed files with 1,902 additions and 1,475 deletions.
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

- [#2328: New Plugin Details page](https://github.com/alphagov/govuk-prototype-kit/pull/2328)

## 13.13.1

### Fixes
Expand Down
4 changes: 0 additions & 4 deletions __tests__/spec/force-https-redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ process.env.KIT_PROJECT_DIR = testDir
process.env.NODE_ENV = 'production'
process.env.USE_HTTPS = 'true'

jest.mock('../../lib/plugins/packages.js', () => {
return {}
})

const app = require('../../server.js')

describe('The Prototype Kit - force HTTPS redirect functionality', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
const { restoreStarterFiles, log } = require('../../utils')
const { restoreStarterFiles, log, waitForApplication } = require('../../utils')
const path = require('path')
const {
loadTemplatesPage,
managePluginsPagePath,
performPluginAction
performPluginAction, managePrototypeContextPath
} = require('../plugin-utils')

const panelCompleteQuery = '[aria-live="polite"] #panel-complete'
const fixtures = path.join(Cypress.config('fixturesFolder'))
const dependentPlugin = 'plugin-fee'
const dependentPluginPackageName = 'plugin-fee'
const dependentPluginName = 'Plugin Fee'
const dependentPluginLocation = [fixtures, 'plugins', dependentPlugin].join(Cypress.config('pathSeparator'))
const dependencyPlugin = 'govuk-frontend'
const dependencyPluginName = 'GOV.UK Frontend'

describe('Install and uninstall Local Plugin via UI Test', async () => {
afterEach(restoreStarterFiles)
beforeEach(() => () => {
cy.exec(`cd ${Cypress.env('projectFolder')} && npm uninstall ${dependentPluginPackageName}`)
cy.task('addToConfigJson', { allowGovukFrontendUninstall: true })
})

it(`The ${dependentPlugin} plugin will be installed`, () => {
log(`The ${dependentPlugin} plugin templates are not available`)
Expand All @@ -26,16 +30,11 @@ describe('Install and uninstall Local Plugin via UI Test', async () => {

log(`Install the ${dependentPlugin} plugin`)
cy.task('waitUntilAppRestarts')
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(dependentPlugin)}&version=${encodeURIComponent(dependentPluginLocation)}`)
cy.visit(`${managePrototypeContextPath}/plugin/fs:${encodeURIComponent(dependentPluginLocation)}/install`)
cy.get('#plugin-action-button').click()

cy.get(panelCompleteQuery, { timeout: 20000 })
.should('be.visible')
cy.get('a').contains('Back to plugins').click()

cy.get('#installed-plugins-link').click()

cy.get(`[data-plugin-package-name="${dependentPlugin}"] button`).contains('Uninstall')

// ------------------------

Expand All @@ -46,42 +45,47 @@ describe('Install and uninstall Local Plugin via UI Test', async () => {
// ------------------------

log('Uninstall the local plugin')
cy.get('a').contains('Plugins').click()
cy.get('#installed-plugins-link').click()
cy.visit('')
cy.visit('/manage-prototype/plugins-installed')

cy.get(`[data-plugin-package-name="${dependentPlugin}"]`)
.scrollIntoView()
.find('button')
.contains('Uninstall')
.find('.plugin-details-link')
.click()

cy.visit(`${managePrototypeContextPath}/plugin/fs:${encodeURIComponent(dependentPluginLocation)}/uninstall`)
cy.get('#plugin-action-button').click()

performPluginAction('uninstall', dependentPlugin, dependentPluginName)

waitForApplication()

// ------------------------

log(`The ${dependentPlugin} plugin templates are not available`)
cy.get('a').contains('Templates').click()
cy.visit('http://localhost:3000/manage-prototype/templates', { retryOnNetworkFailure: true, timeout: 4000 })
cy.get(`[data-plugin-package-name="${dependentPlugin}"]`).should('not.exist')
})

it(`The ${dependentPlugin} plugin and ${dependencyPlugin} will be installed`, () => {
cy.task('addToConfigJson', { allowGovukFrontendUninstall: true })
log(`The ${dependentPlugin} plugin templates are not available`)
loadTemplatesPage()
cy.get(`[data-plugin-package-name="${dependentPlugin}"]`).should('not.exist')

// ------------------------

log(`Uninstall the ${dependencyPlugin} to force the UI to ask for it later`)
cy.task('waitUntilAppRestarts')
cy.visit(`${managePluginsPagePath}/uninstall?package=${encodeURIComponent(dependencyPlugin)}`)
waitForApplication()
cy.visit(`${managePrototypeContextPath}/plugin/installed:${encodeURIComponent(dependencyPlugin)}/uninstall`)
cy.get('#plugin-action-button').click()
performPluginAction('uninstall', dependencyPlugin, dependencyPluginName)

// ------------------------

log(`Install the ${dependentPlugin} plugin and the ${dependencyPlugin}`)
cy.task('waitUntilAppRestarts')
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(dependentPlugin)}&version=${encodeURIComponent(dependentPluginLocation)}`)
waitForApplication()
cy.visit(`${managePrototypeContextPath}/plugin/fs:${encodeURIComponent(dependentPluginLocation)}/install`)
// Should list the dependency plugin
cy.get('li').contains(dependencyPluginName)
cy.get('#plugin-action-button').click()
Expand All @@ -96,8 +100,8 @@ describe('Install and uninstall Local Plugin via UI Test', async () => {
// ------------------------

log('Uninstall the dependency plugin')
cy.task('waitUntilAppRestarts')
cy.visit(`${managePluginsPagePath}/uninstall?package=${encodeURIComponent(dependencyPlugin)}`)
waitForApplication()
cy.visit(`${managePrototypeContextPath}/plugin/installed:${encodeURIComponent(dependencyPlugin)}/uninstall`)
// Should list the dependent plugin
cy.get('li').contains(dependentPluginName)
cy.get('#plugin-action-button').click()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// local dependencies
const { uninstallPlugin, restoreStarterFiles, log } = require('../../utils')
const { uninstallPlugin, restoreStarterFiles, log, waitForApplication } = require('../../utils')
const {
managePluginsPagePath,
loadTemplatesPage,
loadPluginsPage,
manageTemplatesPagePath,
manageInstalledPluginsPagePath
manageInstalledPluginsPagePath,
managePrototypeContextPath
} = require('../plugin-utils')

const panelCompleteQuery = '[aria-live="polite"] #panel-complete'
Expand All @@ -25,7 +25,7 @@ async function installPluginTests ({ plugin, templates, version }) {
log(`Install the ${plugin} plugin`)
if (version) {
cy.task('waitUntilAppRestarts')
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(plugin)}&version=${version}`)
cy.visit(`${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(plugin)}:${version}/install`)

cy.get('#plugin-action-button').click()
} else {
Expand All @@ -36,10 +36,11 @@ async function installPluginTests ({ plugin, templates, version }) {

cy.get(panelCompleteQuery, { timeout: 20000 })
.should('be.visible')
cy.get('a').contains('Back to plugins').click()
cy.get('a').contains('Back to plugin details').should('exist')

cy.get('#installed-plugins-link').click()
cy.get(`[data-plugin-package-name="${plugin}"] button`).contains('Uninstall')
waitForApplication(manageInstalledPluginsPagePath)

cy.get(`[data-plugin-package-name="${plugin}"]`, { timeout: 3000 })

// ------------------------

Expand All @@ -59,15 +60,18 @@ async function installPluginTests ({ plugin, templates, version }) {
// ------------------------

log(`Uninstall the ${plugin} plugin`)
cy.visit(manageInstalledPluginsPagePath)
waitForApplication(manageInstalledPluginsPagePath)

cy.get(`[data-plugin-package-name="${plugin}"] .plugin-details-link`, { timeout: 20000 }).click()

cy.get(`[data-plugin-package-name="${plugin}"] button`).contains('Uninstall').click()
cy.get('.govuk-prototype-kit-plugin-uninstall-button', { timeout: 20000 }).contains('Uninstall').click()

cy.get(panelCompleteQuery, { timeout: 20000 })
.should('be.visible')
cy.get('a').contains('Back to plugins').click()

cy.get(`[data-plugin-package-name="${plugin}"] button`).contains('Install')
cy.visit(`${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(plugin)}:${version}`, { retryOnNetworkFailure: true, timeout: 10000 })

cy.get('.govuk-prototype-kit-plugin-install-button', { timeout: 20000 }).contains('Install').should('exist')
})
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
const path = require('path')

// local dependencies
const { deleteFile, uninstallPlugin, installPlugin, restoreStarterFiles, log } = require('../../utils')
const { deleteFile, uninstallPlugin, installPlugin, restoreStarterFiles, log, waitForApplication } = require('../../utils')
const {
failAction,
performPluginAction,
managePluginsPagePath,
getTemplateLink,
loadInstalledPluginsPage,
loadPluginsPage,
manageInstalledPluginsPagePath
manageInstalledPluginsPagePath,
managePrototypeContextPath
} = require('../plugin-utils')
const { showHideAllLinkQuery, assertVisible, assertHidden } = require('../../step-by-step-utils')

Expand All @@ -26,7 +26,7 @@ const pluginPagePath = '/step-by-step-navigation'
const provePluginFunctionalityWorks = () => {
log(`Prove ${pluginName} functionality works`)

cy.visit(pluginPagePath)
cy.visit(pluginPagePath, { retryOnNetworkFailure: true, timeout: 4000 })

// click toggle button and check that all steps details are visible
cy.get(showHideAllLinkQuery).contains('Show all').click()
Expand All @@ -49,7 +49,7 @@ const provePluginFunctionalityFails = () => {

log(`Prove ${pluginName} functionality fails`)

cy.visit(pluginPagePath)
cy.visit(pluginPagePath, { retryOnNetworkFailure: true, timeout: 4000 })

cy.get(showHideAllLinkQuery).should('not.exist')
}
Expand All @@ -61,13 +61,13 @@ describe('Management plugins: ', () => {
// Load the plugins page, so we don't get any network errors when running the test
loadPluginsPage()
// Now run the test
const installUrl = `${managePluginsPagePath}/install`
const installUrl = `${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(plugin)}/install`
log(`Posting to ${installUrl} without csrf protection`)
cy.request({
url: `${managePluginsPagePath}/install`,
url: installUrl,
method: 'POST',
failOnStatusCode: false,
body: { package: plugin }
body: {}
}).then(response => {
expect(response.status).to.eq(403)
expect(response.body).to.have.property('error', 'invalid csrf token')
Expand All @@ -78,9 +78,11 @@ describe('Management plugins: ', () => {
log(`Install ${plugin}@${version1} directly`)
uninstallPlugin(plugin)

waitForApplication()

loadPluginsPage()

cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(plugin)}&version=${version1}`)
cy.visit(`${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(plugin)}:${version1}/install`)

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

Expand All @@ -91,13 +93,17 @@ describe('Management plugins: ', () => {
log(`Update the ${plugin}@${version1} plugin to ${plugin}@${version2}`)
installPlugin(plugin, version1)

waitForApplication()

loadInstalledPluginsPage()
log(`Update the ${plugin} plugin`)

cy.get(`[data-plugin-package-name="${plugin}"]`)
.scrollIntoView()
.find('button')
.contains('Update')
.find('.plugin-details-link')
.click()

cy.get('.govuk-prototype-kit-plugin-update-button', { timeout: 6000 })
.click()

performPluginAction('update', plugin, pluginName)
Expand Down Expand Up @@ -137,8 +143,10 @@ describe('Management plugins: ', () => {

cy.get(`[data-plugin-package-name="${plugin}"]`)
.scrollIntoView()
.find('button')
.contains('Uninstall')
.find('.plugin-details-link')
.click()

cy.get('.govuk-prototype-kit-plugin-uninstall-button', { timeout: 6000 })
.click()

performPluginAction('uninstall', plugin, pluginName)
Expand All @@ -153,8 +161,10 @@ describe('Management plugins: ', () => {

cy.get(`[data-plugin-package-name="${plugin}"]`)
.scrollIntoView()
.find('button')
.contains('Install')
.find('.plugin-details-link')
.click()

cy.get('.govuk-prototype-kit-plugin-install-button', { timeout: 6000 })
.click()

performPluginAction('install', plugin, pluginName)
Expand All @@ -164,9 +174,9 @@ describe('Management plugins: ', () => {

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

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

Expand All @@ -176,16 +186,27 @@ describe('Management plugins: ', () => {

log('Fail when installing a non existent plugin')
const pkg = 'invalid-prototype-kit-plugin'
const invalidPluginName = 'Invalid Prototype Kit Plugin'
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(pkg)}`)
cy.get('h2').contains(`Install ${invalidPluginName}`)
failAction('install')
cy.request({
url: `${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(pkg)}/install`,
method: 'GET',
failOnStatusCode: false,
retryOnNetworkFailure: true,
timeout: 4000
}).then(response => {
expect(response.status).to.eq(404)
})

// ------------------------

log('Fail when installing a plugin with a non existent version')
cy.visit(`${managePluginsPagePath}/install?package=${encodeURIComponent(plugin)}&version=0.0.1`)
cy.get('h2').contains(`Install ${pluginName}`)
failAction('install')
cy.request({
url: `${managePrototypeContextPath}/plugin/npm:${encodeURIComponent(plugin)}:0.0.1/install`,
method: 'GET',
failOnStatusCode: false,
retryOnNetworkFailure: true,
timeout: 4000
}).then(response => {
expect(response.status).to.eq(404)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('Allow upgrade in URLs', () => {
cy.exec(`cd ${Cypress.env('projectFolder')} && npm install`)

log('Make sure old upgrade URL still works')
cy.visit(`/manage-prototype/plugins/upgrade?package=${encodeURIComponent(plugin)}`)
cy.visit(`/manage-prototype/plugin/npm:${encodeURIComponent(plugin)}/update`)
cy.get('button#plugin-action-button')
.contains('Update')
.click()
Expand Down
Loading

0 comments on commit c5119bf

Please sign in to comment.