Create FF for 'Alignments' Menu Option in IOM
closes OUT-5743 flag=improved_outcomes_management The 'Alignments' kebab menu option in IOM should be hidden behind a 'Site-Admin' level feature flag Test plan: - Tests are sufficient and pass in Jenkins - Ensure that the "Menu Option for Outcome Details Page" FF is only visible for 'Site-Admin' level users - Toggle the FF and ensure that the 'Alignments' option only shows when the FF is enabled Change-Id: I89b6209056b0ea57c0140ae40254bbbc3241e3e4 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/321694 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> QA-Review: Martin Yosifov <martin.yosifov@instructure.com> Product-Review: Kyle Rosenbaum <krosenbaum@instructure.com>
This commit is contained in:
parent
2fbf3f644d
commit
498f788e81
|
@ -56,7 +56,8 @@ class OutcomesController < ApplicationController
|
|||
@context.grants_right?(@current_user, session, :manage_proficiency_calculations)
|
||||
},
|
||||
OUTCOMES_FRIENDLY_DESCRIPTION: Account.site_admin.feature_enabled?(:outcomes_friendly_description),
|
||||
OUTCOME_AVERAGE_CALCULATION: @context.root_account.feature_enabled?(:outcome_average_calculation)
|
||||
OUTCOME_AVERAGE_CALCULATION: @context.root_account.feature_enabled?(:outcome_average_calculation),
|
||||
MENU_OPTION_FOR_OUTCOME_DETAILS_PAGE: Account.site_admin.feature_enabled?(:menu_option_for_outcome_details_page)
|
||||
)
|
||||
|
||||
set_tutorial_js_env
|
||||
|
|
|
@ -62,6 +62,12 @@ improved_lmgb:
|
|||
state: disabled
|
||||
beta:
|
||||
state: disabled
|
||||
menu_option_for_outcome_details_page:
|
||||
type: setting
|
||||
state: hidden
|
||||
applies_to: SiteAdmin
|
||||
display_name: Menu Option for Outcome Details Page
|
||||
description: Adds menu option for accessing alignments at the outcome level with Improved Outcomes Management
|
||||
outcomes_friendly_description:
|
||||
state: hidden
|
||||
applies_to: SiteAdmin
|
||||
|
|
|
@ -179,6 +179,22 @@ describe OutcomesController do
|
|||
end
|
||||
end
|
||||
|
||||
context "menu_option_for_outcome_details_page" do
|
||||
it "returns true if menu_option_for_outcome_details_page feature flage is enabled" do
|
||||
Account.site_admin.enable_feature!(:menu_option_for_outcome_details_page)
|
||||
user_session(@admin)
|
||||
get "index", params: { account_id: @account.id }
|
||||
expect(assigns[:js_env][:MENU_OPTION_FOR_OUTCOME_DETAILS_PAGE]).to be true
|
||||
end
|
||||
|
||||
it "returns false if menu_option_for_outcome_details_page feature flage is disabled" do
|
||||
Account.site_admin.disable_feature!(:menu_option_for_outcome_details_page)
|
||||
user_session(@admin)
|
||||
get "index", params: { account_id: @account.id }
|
||||
expect(assigns[:js_env][:MENU_OPTION_FOR_OUTCOME_DETAILS_PAGE]).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET 'show'" do
|
||||
it "requires authorization" do
|
||||
course_outcome
|
||||
|
|
|
@ -33,6 +33,7 @@ import {
|
|||
} from '@instructure/ui-icons'
|
||||
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||
import {stripHtmlTags} from '@canvas/outcomes/stripHtmlTags'
|
||||
import useCanvasContext from '@canvas/outcomes/react/hooks/useCanvasContext'
|
||||
|
||||
const I18n = useI18nScope('OutcomeManagement')
|
||||
|
||||
|
@ -44,6 +45,7 @@ const OutcomeKebabMenu = ({
|
|||
isGroup,
|
||||
groupDescription,
|
||||
}) => {
|
||||
const {menuOptionForOutcomeDetailsPageFF} = useCanvasContext()
|
||||
const hasDescription =
|
||||
typeof groupDescription === 'string' &&
|
||||
stripHtmlTags(groupDescription).replace(/[\n\r\t\s( )]+/g, '')
|
||||
|
@ -65,7 +67,7 @@ const OutcomeKebabMenu = ({
|
|||
{I18n.t('Edit')}
|
||||
</View>
|
||||
</Menu.Item>
|
||||
{!isGroup && (
|
||||
{menuOptionForOutcomeDetailsPageFF && !isGroup && (
|
||||
<Menu.Item value="alignments">
|
||||
<IconOutcomesLine size="x-small" />
|
||||
<View padding="0 x-large 0 small" data-testid="outcome-kebab-menu-alignments">
|
||||
|
|
|
@ -20,6 +20,7 @@ import React from 'react'
|
|||
import {render, fireEvent} from '@testing-library/react'
|
||||
import {merge} from 'lodash'
|
||||
import OutcomeKebabMenu from '../OutcomeKebabMenu'
|
||||
import OutcomesContext from '@canvas/outcomes/react/contexts/OutcomesContext'
|
||||
|
||||
describe('OutcomeKebabMenu', () => {
|
||||
let onMenuHandlerMock
|
||||
|
@ -36,6 +37,25 @@ describe('OutcomeKebabMenu', () => {
|
|||
props
|
||||
)
|
||||
|
||||
const renderWithProvider = (
|
||||
children,
|
||||
{contextType = 'Account', contextId = '1', menuOptionForOutcomeDetailsPageFF = true} = {}
|
||||
) => {
|
||||
return render(
|
||||
<OutcomesContext.Provider
|
||||
value={{
|
||||
env: {
|
||||
contextType,
|
||||
contextId,
|
||||
menuOptionForOutcomeDetailsPageFF,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</OutcomesContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
onMenuHandlerMock = jest.fn()
|
||||
})
|
||||
|
@ -98,18 +118,42 @@ describe('OutcomeKebabMenu', () => {
|
|||
expect(getByText('Import Outcomes')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders Alignments in Kebab menu if a isGroup is not provided and menu button clicked', () => {
|
||||
const {getByText} = render(<OutcomeKebabMenu {...defaultProps({isGroup: false})} />)
|
||||
const menuButton = getByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
expect(getByText('Alignments')).toBeInTheDocument()
|
||||
})
|
||||
describe('Menu Option for Outcome Details Page FF', () => {
|
||||
it('does not render Alignments menu option if Menu Option for Outcome Details Page FF is disabled', () => {
|
||||
const {queryByText} = renderWithProvider(
|
||||
<OutcomeKebabMenu {...defaultProps({isGroup: false})} />,
|
||||
{
|
||||
menuOptionForOutcomeDetailsPageFF: false,
|
||||
}
|
||||
)
|
||||
const menuButton = queryByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
expect(queryByText('Alignments')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not render Alignments in Kebab menu if a isGroup is provided and menu button clicked', () => {
|
||||
const {queryByText} = render(<OutcomeKebabMenu {...defaultProps({isGroup: true})} />)
|
||||
const menuButton = queryByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
expect(queryByText('Alignments')).not.toBeInTheDocument()
|
||||
it('renders Alignments in Kebab menu if a isGroup is not provided and menu button clicked and FF is enabled', () => {
|
||||
const {getByText} = renderWithProvider(
|
||||
<OutcomeKebabMenu {...defaultProps({isGroup: false})} />,
|
||||
{
|
||||
menuOptionForOutcomeDetailsPageFF: true,
|
||||
}
|
||||
)
|
||||
const menuButton = getByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
expect(getByText('Alignments')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not render Alignments in Kebab menu if a isGroup is provided and menu button clicked and FF is disabled', () => {
|
||||
const {queryByText} = renderWithProvider(
|
||||
<OutcomeKebabMenu {...defaultProps({isGroup: true})} />,
|
||||
{
|
||||
menuOptionForOutcomeDetailsPageFF: true,
|
||||
}
|
||||
)
|
||||
const menuButton = queryByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
expect(queryByText('Alignments')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('with Kebab menu open', () => {
|
||||
|
@ -144,7 +188,9 @@ describe('OutcomeKebabMenu', () => {
|
|||
})
|
||||
|
||||
it('handles click on Alignments item', () => {
|
||||
const {getByText} = render(<OutcomeKebabMenu {...defaultProps()} />)
|
||||
const {getByText} = renderWithProvider(<OutcomeKebabMenu {...defaultProps()} />, {
|
||||
menuOptionForOutcomeDetailsPageFF: true,
|
||||
})
|
||||
const menuButton = getByText(groupMenuTitle)
|
||||
fireEvent.click(menuButton)
|
||||
const menuItem = getByText('Alignments')
|
||||
|
|
|
@ -38,6 +38,7 @@ export const getContext = isMobileView => {
|
|||
const rootIds = [globalRootId, treeBrowserAccountGroupId, treeBrowserRootGroupId]
|
||||
const accountLevelMasteryScalesFF = ENV.ACCOUNT_LEVEL_MASTERY_SCALES
|
||||
const outcomeAllowAverageCalculationFF = ENV.OUTCOME_AVERAGE_CALCULATION
|
||||
const menuOptionForOutcomeDetailsPageFF = ENV.MENU_OPTION_FOR_OUTCOME_DETAILS_PAGE
|
||||
|
||||
return {
|
||||
env: {
|
||||
|
@ -56,6 +57,7 @@ export const getContext = isMobileView => {
|
|||
rootIds,
|
||||
accountLevelMasteryScalesFF,
|
||||
outcomeAllowAverageCalculationFF,
|
||||
menuOptionForOutcomeDetailsPageFF,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ const useCanvasContext = () => {
|
|||
const rootIds = context?.env?.rootIds
|
||||
const accountLevelMasteryScalesFF = context?.env?.accountLevelMasteryScalesFF
|
||||
const outcomeAllowAverageCalculationFF = context?.env?.outcomeAllowAverageCalculationFF
|
||||
const menuOptionForOutcomeDetailsPageFF = context?.env?.menuOptionForOutcomeDetailsPageFF
|
||||
|
||||
return {
|
||||
contextType,
|
||||
|
@ -55,6 +56,7 @@ const useCanvasContext = () => {
|
|||
rootIds,
|
||||
accountLevelMasteryScalesFF,
|
||||
outcomeAllowAverageCalculationFF,
|
||||
menuOptionForOutcomeDetailsPageFF,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue