░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/var/www/canvas/ui/features/brand_configs/react/__tests__
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: CollectionView.test.js
/* * Copyright (C) 2020 - present Instructure, Inc. * * This file is part of Canvas. * * Canvas is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, version 3 of the License. * * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ import fetchMock from 'fetch-mock' import React from 'react' import {render, fireEvent} from '@testing-library/react' import {within} from '@testing-library/dom' import Subject from '../CollectionView' import * as submitHtmlForm from '@canvas/theme-editor/submitHtmlForm' const OUR_ACCOUNT_ID = '123' const ACTIVE_BASIS = { name: 'Account-shared Theme', md5: '00112233445566778899aabbccddeeff', } const DELETABLE_ID = 9847 const DELETABLE_BASIS = { name: 'Deletable Theme', md5: '01234567012345670123456701234567', } const props = { sharedBrandConfigs: [ { account_id: null, name: 'Canned Template Theme', id: 128, brand_config: { md5: '001122334455667788990022446688aa', variables: { foo: '#123', }, }, }, { account_id: null, name: 'Another Canned Template Theme', id: 127, brand_config: { md5: '00112233445566778899001122334455', variables: { foo: '#123', }, }, }, { account_id: OUR_ACCOUNT_ID, name: ACTIVE_BASIS.name, id: 123, brand_config: { md5: ACTIVE_BASIS.md5, variables: { foo: '#123', }, }, }, { account_id: OUR_ACCOUNT_ID, name: DELETABLE_BASIS.name, id: DELETABLE_ID, brand_config: { md5: DELETABLE_BASIS.md5, variables: { foo: '#fff', }, }, }, ], activeBrandConfig: { md5: ACTIVE_BASIS.md5, variables: {}, }, accountID: OUR_ACCOUNT_ID, brandableVariableDefaults: { foo: { default: '#321', type: 'color', variable_name: 'foo', }, otherFoo: { default: '$foo', type: 'color', variable_name: 'Other Foo', }, }, baseBrandableVariables: { foo: 'red', }, } describe('CollectionView', () => { const deleteURL = new RegExp('/api/v1/shared_brand_configs/(.+)') let mockedSubmitForm const savedSubmit = submitHtmlForm.default const {location: savedLocation} = window beforeEach(() => { fetchMock.delete(deleteURL, {}) mockedSubmitForm = jest.fn() submitHtmlForm.default = mockedSubmitForm // JS DOM doesn't implement location.reload delete window.location window.location = {reload: jest.fn()} }) afterEach(() => { fetchMock.restore() submitHtmlForm.default = savedSubmit window.location = savedLocation }) it('renders', () => { const {container} = render(<Subject {...props} />) const title = container.querySelector('h1') expect(title.innerHTML).toBe('Themes') }) it('always shows the default theme in the Templates', () => { const {getByTestId} = render(<Subject {...props} />) const templates = getByTestId('container-templates-section') const cardButtons = within(templates).getAllByTestId('themecard-name-button') const found = cardButtons.some(card => { return !!within(card).queryByText('Default Template') }) expect(found).toBe(true) }) it('shows cards in Templates for all sharedBrandConfigs with null account', () => { const globalConfigNames = props.sharedBrandConfigs .filter(c => c.account_id === null) .map(c => c.name) const {getByTestId} = render(<Subject {...props} />) const templates = getByTestId('container-templates-section') const buttons = within(templates).getAllByTestId('themecard-name-button') expect(globalConfigNames.every(c => buttons.some(cc => within(cc).queryByText(c)))).toBe(true) }) it('shows cards in My Themes for all sharedBrandConfigs that have my account', () => { const localConfigNames = props.sharedBrandConfigs .filter(c => c.account_id === props.accountID) .map(c => c.name) const {getByTestId} = render(<Subject {...props} />) const templates = getByTestId('container-mythemes-section') const buttons = within(templates).getAllByTestId('themecard-name-button') expect(localConfigNames.every(c => buttons.some(cc => within(cc).queryByText(c)))).toBe(true) }) it('shows the activeBrandConfig even when its md5 is not in the list of shared ones', () => { const activeBrandConfig = { md5: '43214321432143214321432143124312', name: 'Very Special', variables: {}, } const newProps = {...props, activeBrandConfig} const {getAllByTestId} = render(<Subject {...newProps} />) const cardButtons = getAllByTestId('themecard-name-button') // should be two extra ones (the Default Template and the new activeBrandConfig) expect(cardButtons).toHaveLength(props.sharedBrandConfigs.length + 2) expect(cardButtons.find(card => within(card).queryByText('Very Special'))).toBeDefined() }) it('shows the New Theme button', () => { const {getByTestId} = render(<Subject {...props} />) expect(getByTestId('new-theme-button')).toBeInTheDocument() }) it('shows all possible things to base a new theme on when New Theme is clicked', () => { const names = props.sharedBrandConfigs.map(c => c.name) names.unshift('Default Template') const {getByTestId, getAllByTestId} = render(<Subject {...props} />) const newThemeButton = getByTestId('new-theme-button') fireEvent.click(newThemeButton) const menuItems = getAllByTestId('new-theme-menu-item') expect(names.every(name => menuItems.some(item => within(item).queryByText(name)))).toBe(true) }) it('submits the right form to create a new theme when basis is the active config', () => { const {getByTestId, getAllByTestId} = render(<Subject {...props} />) const newThemeButton = getByTestId('new-theme-button') fireEvent.click(newThemeButton) const menuItems = getAllByTestId('new-theme-menu-item') const basis = menuItems.find(item => within(item).queryByText(ACTIVE_BASIS.name)) expect(basis).toBeDefined() fireEvent.click(basis) expect(mockedSubmitForm).toHaveBeenCalledWith( `/accounts/${OUR_ACCOUNT_ID}/brand_configs/save_to_user_session`, 'POST', undefined ) }) it('submits the right form to create a new theme when basis is not the active config', () => { const {getByTestId, getAllByTestId} = render(<Subject {...props} />) const newThemeButton = getByTestId('new-theme-button') fireEvent.click(newThemeButton) const menuItems = getAllByTestId('new-theme-menu-item') const basis = menuItems.find(item => within(item).queryByText(DELETABLE_BASIS.name)) expect(basis).toBeDefined() fireEvent.click(basis) expect(mockedSubmitForm).toHaveBeenCalledWith( `/accounts/${OUR_ACCOUNT_ID}/brand_configs/save_to_user_session`, 'POST', DELETABLE_BASIS.md5 ) }) it('does not allow system themes to be deleted', () => { const {getByTestId} = render(<Subject {...props} />) const templates = getByTestId('container-templates-section') const cardButtons = within(templates).queryAllByTestId('themecard-delete-button') expect(cardButtons).toHaveLength(0) }) it('allows my themes to be deleted except the active one', () => { const {getByTestId} = render(<Subject {...props} />) const templates = getByTestId('container-mythemes-section') const cardButtons = within(templates).queryAllByTestId('themecard-delete-button') expect(cardButtons).toHaveLength(1) // not the active one, only the other one }) it('allows the active theme to be deleted if multiple themes reflect the active one', () => { const dupOfActive = { account_id: OUR_ACCOUNT_ID, name: 'Duplicate of Account-shared Theme', id: 345, brand_config: { md5: ACTIVE_BASIS.md5, variables: { foo: '#123', }, }, } const sharedBrandConfigs = [...props.sharedBrandConfigs, dupOfActive] const newProps = {...props, sharedBrandConfigs} const {getByTestId} = render(<Subject {...newProps} />) const templates = getByTestId('container-mythemes-section') const cardButtons = within(templates).queryAllByTestId('themecard-delete-button') expect(cardButtons).toHaveLength(3) // BOTH the active and deletable, plus the dup }) it('submits the right form to edit an existing theme', () => { const {getAllByTestId} = render(<Subject {...props} />) const cardButtons = getAllByTestId('themecard-name-button') const card = cardButtons.find(c => within(c).queryByText(DELETABLE_BASIS.name)) fireEvent.click(card) expect(mockedSubmitForm).toHaveBeenCalledWith( `/accounts/${OUR_ACCOUNT_ID}/brand_configs/save_to_user_session`, 'POST', DELETABLE_BASIS.md5 ) }) it('submits the right form to edit the active theme', () => { const {getAllByTestId} = render(<Subject {...props} />) const cardButtons = getAllByTestId('themecard-name-button') const card = cardButtons.find(c => within(c).queryByText(ACTIVE_BASIS.name)) fireEvent.click(card) expect(mockedSubmitForm).toHaveBeenCalledWith( `/accounts/${OUR_ACCOUNT_ID}/brand_configs/save_to_user_session`, 'POST', undefined ) }) // Note that we've carefully set up the test props so that exactly one // brandConfig is deletable. Because we use getByText here, if that // becomes no longer true, this test will fail. it('makes the correct DELETE API call on a deletion', async () => { const {getByText, getByLabelText} = render(<Subject {...props} />) const deleteButton = getByText('Delete theme').closest('button') fireEvent.click(deleteButton) const deleteConfirmModal = getByLabelText('Delete Theme?') const confirmButton = within(deleteConfirmModal).getByText('Delete').closest('button') fireEvent.click(confirmButton) await fetchMock.flush(false) expect(fetchMock.done()).toBe(true) const callMatch = fetchMock.lastCall(deleteURL)[0].match(deleteURL) expect(parseInt(callMatch[1], 10)).toBe(DELETABLE_ID) }) it('does not make any DELETE API call when the delete is canceled', async () => { const {getByText, getByLabelText} = render(<Subject {...props} />) const deleteButton = getByText('Delete theme').closest('button') fireEvent.click(deleteButton) const deleteConfirmModal = getByLabelText('Delete Theme?') const confirmButton = within(deleteConfirmModal).getByText('Cancel').closest('button') fireEvent.click(confirmButton) await fetchMock.flush(false) expect(fetchMock.called(deleteURL)).toBe(false) }) })
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 CollectionView.test.js
JS
10.9 KB
2023-09-24 03:39
EDIT