-
Notifications
You must be signed in to change notification settings - Fork 19
feat(devices): add remote platform erase support #3206
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
Merged
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
58b8325
feat(devices): add remote platform erase (RPE) feature
nmgaston 3c50c8b
fix: fix build and test issues
nmgaston 50993b6
feat: remote platform erase improvements
nmgaston f872ff3
fix: fix renaming issue for rpe
nmgaston b9f92cd
test: skip RPE tests if ran in cloud mode
nmgaston 3e9c0ef
Merge remote-tracking branch 'origin/main' into remotePlatformErase
nmgaston 712fec4
chore(devices): cleanup after rebase
nmgaston 80c4d77
fix: revert back to head changes
nmgaston e82a9a2
fix: send payload from server for error messages
nmgaston 3b98195
feat: add success messages for os clear success and CSME clear success
nmgaston b333f9c
Merge branch 'main' into remotePlatformErase
nmgaston 39886c9
feat: add pyrite disk encryption for SSD erase
nmgaston c280bef
Merge branch 'remotePlatformErase' of https://github.com/device-manag…
nmgaston a41e64e
feat: add user consent code for RPE
nmgaston 81ca705
Merge branch 'main' into remotePlatformErase
nmgaston ccf6bcc
fix: language translation missed
nmgaston b440de8
Merge branch 'remotePlatformErase' of https://github.com/device-manag…
nmgaston f5d1840
Revert "feat: add user consent code for RPE"
nmgaston 9e7c36a
revert: revert user consent and blocking rpe changes for cloud mode
nmgaston 7cb4ebb
Merge branch 'main' into remotePlatformErase
nmgaston 2390145
fix: build after merge
nmgaston 7210e13
chore(docker): update Dockerfile
nmgaston b65818b
revert(docker): revert Dockerfile update
nmgaston 9ba37cd
feat: add user consent mode for CCM mode and when ACM UserConsent mod…
nmgaston 54c1fc4
fix: issue with keeping RPE state between tabs in cloud
nmgaston 0f5100d
Merge branch 'main' into remotePlatformErase
nmgaston 67d7624
style: UI changes from review
nmgaston 9b6efa3
style: UI changes from review
nmgaston e51bdf4
Merge branch 'main' into remotePlatformErase
nmgaston f1e2174
feat: add 32 byte limit for Pyrite drive when wiping SSD that is encr…
nmgaston fac4bbb
chore: rebase
nmgaston 2c0484a
chore: fix lint issue
nmgaston e565265
fix: review comments
nmgaston 24f7eb2
Merge branch 'main' into remotePlatformErase
nmgaston 1eb5340
fix: lint issue
nmgaston fde124f
Merge branch 'main' into remotePlatformErase
nmgaston 7abdb05
fix: language file inconsistencies
nmgaston 83cea46
Merge branch 'main' into remotePlatformErase
nmgaston 195fa82
fix: merge conflict issues
nmgaston 2f7d8dc
fix: update incorrect error message
nmgaston File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
258 changes: 258 additions & 0 deletions
258
cypress/e2e/integration/device/remote-platform-erase.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,258 @@ | ||
| /********************************************************************* | ||
| * Copyright (c) Intel Corporation 2022 | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| **********************************************************************/ | ||
|
|
||
| import { httpCodes } from '../../fixtures/api/httpCodes' | ||
| import { eventLogs } from '../../fixtures/api/eventlog' | ||
|
|
||
| const describeWhenNotCloud = Cypress.env('CLOUD') ? describe.skip : describe | ||
|
|
||
| const navigateToRemotePlatformErase = ( | ||
| featuresBody: object = eventLogs.remotePlatformErase.supportedDisabled.response | ||
| ): void => { | ||
| cy.myIntercept('GET', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: featuresBody | ||
| }).as('get-features') | ||
|
|
||
| cy.myIntercept('GET', 'devices?$top=25&$skip=0&$count=true', { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.devices.success.response | ||
| }).as('get-devices') | ||
|
|
||
| cy.myIntercept('GET', /devices\/.*$/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.devices.success.response | ||
| }).as('get-device-by-id') | ||
|
|
||
| cy.myIntercept('GET', /devices\/tags/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: [] | ||
| }).as('get-tags') | ||
|
|
||
| cy.myIntercept('GET', /.*power.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: { powerstate: 2 } | ||
| }).as('get-powerstate') | ||
|
|
||
| cy.myIntercept('GET', /.*general.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.general.success.response | ||
| }).as('get-general') | ||
|
|
||
| cy.myIntercept('GET', /.*version.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.version.success.response | ||
| }).as('get-version') | ||
|
|
||
| cy.myIntercept('GET', /.*amt\/boot\/remoteErase.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.capabilities.response | ||
| }).as('get-capabilities') | ||
|
|
||
| cy.myIntercept('GET', /.*alarmOccurrences.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.alarmOccurrences.success.response | ||
| }).as('get-alarms') | ||
|
|
||
| cy.goToPage('Devices') | ||
| cy.wait('@get-devices').its('response.statusCode').should('eq', 200) | ||
|
|
||
| cy.get('mat-row').first().click() | ||
| cy.wait('@get-device-by-id').its('response.statusCode').should('eq', 200) | ||
|
|
||
| cy.get('.mat-mdc-list-item-title').contains('Remote Platform Erase').click() | ||
| cy.wait('@get-capabilities') | ||
| // Wait for Angular to finish loading (isLoading signal → mat-progress-bar disappears) | ||
| cy.get('mat-progress-bar').should('not.exist') | ||
| } | ||
|
|
||
| describeWhenNotCloud('Remote Platform Erase', () => { | ||
| beforeEach(() => { | ||
| cy.setup() | ||
| }) | ||
|
|
||
| it('should show "not supported" message when remoteEraseSupported is false', () => { | ||
| navigateToRemotePlatformErase(eventLogs.remotePlatformErase.notSupported.response) | ||
| cy.wait('@get-features') | ||
|
|
||
| cy.get('[data-cy="remoteEraseCheckbox"]').should('not.exist') | ||
| cy.get('mat-icon').contains('info').should('exist') | ||
| }) | ||
|
|
||
| it('should show checkbox when supported but not enabled', () => { | ||
| navigateToRemotePlatformErase(eventLogs.remotePlatformErase.supportedDisabled.response) | ||
| cy.wait('@get-features') | ||
|
|
||
| cy.get('[data-cy="remoteEraseCheckbox"]').should('exist') | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]').should('have.attr', 'aria-checked', 'false') | ||
| cy.get('[data-cy="initiateEraseButton"]').should('not.exist') | ||
| }) | ||
|
|
||
| it('should show checkbox checked when rpe is true in API response', () => { | ||
| navigateToRemotePlatformErase(eventLogs.remotePlatformErase.supportedEnabled.response) | ||
| cy.wait('@get-features') | ||
|
|
||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]').should('have.attr', 'aria-checked', 'true') | ||
| cy.get('[data-cy="initiateEraseButton"]').should('be.visible') | ||
| }) | ||
|
|
||
| it('should enable the feature and show initiate erase button after toggling on', () => { | ||
| cy.myIntercept('POST', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedEnabled.response | ||
| }).as('post-features') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features').its('request.body.rpe').should('eq', true) | ||
|
|
||
| cy.get('[data-cy="initiateEraseButton"]').should('be.visible') | ||
| }) | ||
|
|
||
| it('should disable the feature after toggling off', () => { | ||
| // Register disable handler first (LIFO: last registered = first matched) | ||
| // so the second POST (disable click) hits the disable response | ||
| cy.intercept( | ||
| { method: 'POST', url: /.*amt\/features.*/, times: 1 }, | ||
| { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedDisabled.response | ||
| } | ||
| ).as('post-features-disable') | ||
|
|
||
| // Register enable handler second so it matches the first POST (enable click) | ||
| cy.intercept( | ||
| { method: 'POST', url: /.*amt\/features.*/, times: 1 }, | ||
| { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedEnabled.response | ||
| } | ||
| ).as('post-features-enable') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| // Enable first | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features-enable').its('request.body.rpe').should('eq', true) | ||
|
|
||
| // Then disable | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features-disable').its('request.body.rpe').should('eq', false) | ||
|
|
||
| cy.get('[data-cy="initiateEraseButton"]').should('not.exist') | ||
| }) | ||
|
|
||
| it('should call the remoteErase API when erase is confirmed in the dialog', () => { | ||
| cy.myIntercept('POST', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedEnabled.response | ||
| }).as('post-features') | ||
|
|
||
| cy.myIntercept('POST', /.*amt\/boot\/remoteErase.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: {} | ||
| }).as('post-erase') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| // Enable the feature first | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features') | ||
|
|
||
| cy.get('[data-cy="eraseCapCheckbox"]').first().find('input[type="checkbox"]').check({ force: true }) | ||
| cy.get('[data-cy="initiateEraseButton"]').click() | ||
|
|
||
| cy.get('mat-dialog-container').should('be.visible') | ||
| cy.get('mat-dialog-container').contains('button', 'Yes').click() | ||
|
|
||
| cy.wait('@post-erase').its('response.statusCode').should('eq', 200) | ||
| }) | ||
|
|
||
| it('should not call the remoteErase API when erase is cancelled', () => { | ||
| cy.myIntercept('POST', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedEnabled.response | ||
| }).as('post-features') | ||
|
|
||
| cy.myIntercept('POST', /.*amt\/boot\/remoteErase.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: {} | ||
| }).as('post-erase') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| // Enable the feature first | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features') | ||
|
|
||
| cy.get('[data-cy="eraseCapCheckbox"]').first().find('input[type="checkbox"]').check({ force: true }) | ||
| cy.get('[data-cy="initiateEraseButton"]').click() | ||
|
|
||
| cy.get('mat-dialog-container').should('be.visible') | ||
| cy.get('mat-dialog-container').contains('button', 'No').click() | ||
|
|
||
| cy.get('@post-erase.all').should('have.length', 0) | ||
| }) | ||
|
|
||
| it('should show error snackbar when toggling feature fails', () => { | ||
| cy.myIntercept('POST', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.INTERNAL_SERVER_ERROR, | ||
| body: {} | ||
| }).as('post-features-error') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features-error') | ||
|
|
||
| cy.get('mat-snack-bar-container').should('be.visible') | ||
| }) | ||
|
|
||
| it('should show error snackbar when erase API fails', () => { | ||
| cy.myIntercept('POST', /.*amt\/features.*/, { | ||
| statusCode: httpCodes.SUCCESS, | ||
| body: eventLogs.remotePlatformErase.supportedEnabled.response | ||
| }).as('post-features') | ||
|
|
||
| cy.myIntercept('POST', /.*amt\/boot\/remoteErase.*/, { | ||
| statusCode: httpCodes.INTERNAL_SERVER_ERROR, | ||
| body: {} | ||
| }).as('post-erase-error') | ||
|
|
||
| navigateToRemotePlatformErase() | ||
| cy.wait('@get-features') | ||
|
|
||
| // Enable the feature first | ||
| cy.get('[data-cy="remoteEraseCheckbox"] button[role="switch"]') | ||
| .should('not.have.attr', 'aria-disabled', 'true') | ||
| .click() | ||
| cy.wait('@post-features') | ||
|
|
||
| cy.get('[data-cy="eraseCapCheckbox"]').first().find('input[type="checkbox"]').check({ force: true }) | ||
| cy.get('[data-cy="initiateEraseButton"]').click() | ||
| cy.get('mat-dialog-container').contains('button', 'Yes').click() | ||
|
|
||
| cy.wait('@post-erase-error') | ||
| cy.get('mat-snack-bar-container').should('be.visible') | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.