Skip to content
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Changed
---

Update Generational Plans default sort to show newest (G8) -> oldest (G6) ([#13234](https://github.com/linode/manager/pull/13234))
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,13 @@
.findByTitle(`Add a Node Pool: ${mockCluster.label}`)
.should('be.visible')
.within(() => {
// For the "Dedicated 4 GB", use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();

ui.autocompletePopper.find().within(() => {

Check warning on line 1411 in packages/manager/cypress/e2e/core/kubernetes/lke-update.spec.ts

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Refactor this code to not nest functions more than 4 levels deep. Raw Output: {"ruleId":"sonarjs/no-nested-functions","severity":1,"message":"Refactor this code to not nest functions more than 4 levels deep.","line":1411,"column":50,"nodeType":null,"endLine":1411,"endColumn":52}
cy.findByText('G6 Dedicated').should('be.visible').click();
});

cy.findByText('Dedicated 4 GB')
.should('be.visible')
.closest('tr')
Expand Down
18 changes: 18 additions & 0 deletions packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
cy.get('[data-qa-tp="Linode Plan"]')
.should('be.visible')
.within(() => {
// For the Dedicated 8 GB, Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();

Check warning on line 127 in packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Define a constant instead of duplicating this literal 3 times. Raw Output: {"ruleId":"sonarjs/no-duplicate-string","severity":1,"message":"Define a constant instead of duplicating this literal 3 times.","line":127,"column":37,"nodeType":"Literal","endLine":127,"endColumn":54}
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();

Check warning on line 129 in packages/manager/cypress/e2e/core/linodes/alerts-create.spec.ts

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Define a constant instead of duplicating this literal 3 times. Raw Output: {"ruleId":"sonarjs/no-duplicate-string","severity":1,"message":"Define a constant instead of duplicating this literal 3 times.","line":129,"column":25,"nodeType":"Literal","endLine":129,"endColumn":39}
});

cy.get('[data-qa-plan-row="Dedicated 8 GB"]').click();
});
cy.get('[type="password"]').should('be.visible').scrollIntoView();
Expand Down Expand Up @@ -283,6 +289,12 @@
cy.get('[data-qa-tp="Linode Plan"]')
.should('be.visible')
.within(() => {
// For the Dedicated 8 GB, Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();
});

cy.get('[data-qa-plan-row="Dedicated 8 GB"]').click();
});
cy.get('[type="password"]').should('be.visible').scrollIntoView();
Expand Down Expand Up @@ -432,6 +444,12 @@
cy.get('[data-qa-tp="Linode Plan"]')
.should('be.visible')
.within(() => {
// For the Dedicated 8 GB, Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();
});

cy.get('[data-qa-plan-row="Dedicated 8 GB"]').click();
});
cy.get('[type="password"]').should('be.visible').scrollIntoView();
Expand Down
10 changes: 10 additions & 0 deletions packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@
linodeCreatePage.setLabel(linodeLabel);
linodeCreatePage.selectImage('Debian 12');
linodeCreatePage.selectRegionById(linodeRegion.id);

// For the "Dedicated 4 GB" plan under the "Dedicated CPU" plan type, use filter to select G6 Dedicated instead of relying on pagination
if (planConfig.planType === 'Dedicated CPU') {
ui.autocomplete.findByLabel('Dedicated Plans').click();

ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();

Check warning on line 102 in packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts

View workflow job for this annotation

GitHub Actions / ESLint Review (manager)

[eslint] reported by reviewdog 🐢 Define a constant instead of duplicating this literal 25 times. Raw Output: {"ruleId":"sonarjs/no-duplicate-string","severity":1,"message":"Define a constant instead of duplicating this literal 25 times.","line":102,"column":52,"nodeType":"Literal","endLine":102,"endColumn":64}
});
}

linodeCreatePage.selectPlan(
planConfig.planType,
planConfig.planLabel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ describe('OneClick Apps (OCA)', () => {
cy.focused().type(`${region.id}{enter}`);

// Choose a Linode plan
// For the Dedicated 8 GB, Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();
});
cy.get('[data-qa-plan-row="Dedicated 8 GB"]')
.closest('tr')
.within(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ const fillOutLinodeForm = (label: string, regionName: string) => {
cy.focused().type(label);

cy.findByText('Dedicated CPU').should('be.visible').click();

// Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();
});

cy.get('[id="g6-dedicated-2"]').click();
cy.findByLabelText('Root Password').should('be.visible').type(password);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,13 @@ describe('Community Stackscripts integration tests', () => {

// An error message shows up when no region is selected
cy.contains('Plan is required.').should('be.visible');

// For the Dedicated 8 GB, Use filter to select G6 Dedicated instead of relying on pagination
ui.autocomplete.findByLabel('Dedicated Plans').click();
ui.autocompletePopper.find().within(() => {
cy.findByText('G6 Dedicated').should('be.visible').click();
});

cy.get('[data-qa-plan-row="Dedicated 8 GB"]')
.closest('tr')
.within(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
filterPlansByGpuType,
filterPlansByType,
getAvailableTypes,
getGenerationRank,
supportsTypeFiltering,
} from './planFilters';

Expand Down Expand Up @@ -240,4 +241,32 @@ describe('planFilters utilities', () => {
expect(result).toEqual(gpuPlans);
});
});

describe('getGenerationRank', () => {
it('returns higher rank for newer generations', () => {
expect(getGenerationRank('g8-dedicated-4-2')).toBeGreaterThan(
getGenerationRank('g7-dedicated-4-2')
);
expect(getGenerationRank('g7-dedicated-4-2')).toBeGreaterThan(
getGenerationRank('g6-dedicated-2')
);
});

it('handles multi-digit generations correctly', () => {
expect(getGenerationRank('g10-dedicated-2')).toBeGreaterThan(
getGenerationRank('g8-dedicated-4-2')
);
expect(getGenerationRank('g11-dedicated-2')).toBeGreaterThan(
getGenerationRank('g10-dedicated-2')
);
});

it('returns 0 for unknown generations', () => {
expect(getGenerationRank('legacy-plan')).toBe(0);
expect(getGenerationRank('gg-xyz')).toBe(0);
expect(getGenerationRank('g-pqr')).toBe(0);
expect(getGenerationRank('x123')).toBe(0);
expect(getGenerationRank('')).toBe(0);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,26 @@ export const filterPlansByGeneration = (
// Type Filtering
// ============================================================================

/**
* Returns the numeric generation of a plan based on its ID.
* Higher generation number = newer plan (shown first).
*
* Example:
* - "g8-dedicated-4-2" -> 8
* - "g1-accelerated-netint-vpu" -> 1
* - "legacy-plan" -> 0
*/
export const getGenerationRank = (planId: string): number => {
const generation = planId.split('-')[0]; // eg., "g8" or "legacy"

// Safe fallback: must start with "g"
if (!generation.startsWith('g')) return 0;

const num = Number(generation.slice(1));

return Number.isFinite(num) ? num : 0;
};

/**
* Filter plans by type within a generation
*
Expand All @@ -88,9 +108,11 @@ export const filterPlansByType = (
generation: PlanFilterGeneration,
type: PlanFilterType
): PlanWithAvailability[] => {
// "All" returns all plans unchanged
// "All" returns all plans, sorted from newest to oldest generations
if (type === PLAN_FILTER_ALL) {
return plans;
return [...plans].sort(
(a, b) => getGenerationRank(b.id) - getGenerationRank(a.id)
);
}

// G7, G6, and "All" generation only have "All" option (no sub-types)
Expand Down