-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Revert "feat(RLS): RESTful apis and react view for RLS (#22325)…
…"" This reverts commit 6306803.
- Loading branch information
1 parent
961bd37
commit f88f49d
Showing
21 changed files
with
2,643 additions
and
161 deletions.
There are no files selected for viewing
This file contains 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
259 changes: 259 additions & 0 deletions
259
superset-frontend/src/views/CRUD/rowlevelsecurity/RowLevelSecurityList.test.tsx
This file contains 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,259 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
import React from 'react'; | ||
import fetchMock from 'fetch-mock'; | ||
import RowLevelSecurityList from 'src/views/CRUD/rowlevelsecurity/RowLevelSecurityList'; | ||
import { render, screen, within } from 'spec/helpers/testing-library'; | ||
import { act } from 'react-dom/test-utils'; | ||
import { MemoryRouter } from 'react-router-dom'; | ||
import { QueryParamProvider } from 'use-query-params'; | ||
import { styledMount as mount } from 'spec/helpers/theming'; | ||
import { Provider } from 'react-redux'; | ||
import configureStore from 'redux-mock-store'; | ||
import thunk from 'redux-thunk'; | ||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; | ||
import ListView from 'src/components/ListView/ListView'; | ||
import userEvent from '@testing-library/user-event'; | ||
|
||
const ruleListEndpoint = 'glob:*/api/v1/rowlevelsecurity/?*'; | ||
const ruleInfoEndpoint = 'glob:*/api/v1/rowlevelsecurity/_info*'; | ||
|
||
const mockRules = [ | ||
{ | ||
changed_on_delta_humanized: '1 days ago', | ||
clause: '1=1', | ||
description: 'some description', | ||
filter_type: 'Regular', | ||
group_key: 'group-1', | ||
id: 1, | ||
name: 'rule 1', | ||
roles: [ | ||
{ | ||
id: 3, | ||
name: 'Alpha', | ||
}, | ||
{ | ||
id: 5, | ||
name: 'granter', | ||
}, | ||
], | ||
tables: [ | ||
{ | ||
id: 6, | ||
table_name: 'flights', | ||
}, | ||
{ | ||
id: 13, | ||
table_name: 'messages', | ||
}, | ||
], | ||
}, | ||
{ | ||
changed_on_delta_humanized: '2 days ago', | ||
clause: '2=2', | ||
description: 'some description 2', | ||
filter_type: 'Base', | ||
group_key: 'group-1', | ||
id: 2, | ||
name: 'rule 2', | ||
roles: [ | ||
{ | ||
id: 3, | ||
name: 'Alpha', | ||
}, | ||
{ | ||
id: 5, | ||
name: 'granter', | ||
}, | ||
], | ||
tables: [ | ||
{ | ||
id: 6, | ||
table_name: 'flights', | ||
}, | ||
{ | ||
id: 13, | ||
table_name: 'messages', | ||
}, | ||
], | ||
}, | ||
]; | ||
fetchMock.get(ruleListEndpoint, { result: mockRules, count: 2 }); | ||
fetchMock.get(ruleInfoEndpoint, { permissions: ['can_read', 'can_write'] }); | ||
global.URL.createObjectURL = jest.fn(); | ||
|
||
const mockUser = { | ||
userId: 1, | ||
}; | ||
|
||
const mockedProps = {}; | ||
|
||
const mockStore = configureStore([thunk]); | ||
const store = mockStore({}); | ||
|
||
describe('RulesList Enzyme', () => { | ||
let wrapper: any; | ||
|
||
beforeAll(async () => { | ||
fetchMock.resetHistory(); | ||
wrapper = mount( | ||
<MemoryRouter> | ||
<Provider store={store}> | ||
<RowLevelSecurityList {...mockedProps} user={mockUser} /> | ||
</Provider> | ||
</MemoryRouter>, | ||
); | ||
|
||
await waitForComponentToPaint(wrapper); | ||
}); | ||
|
||
it('renders', () => { | ||
expect(wrapper.find(RowLevelSecurityList)).toExist(); | ||
}); | ||
it('renders a ListView', () => { | ||
expect(wrapper.find(ListView)).toExist(); | ||
}); | ||
it('fetched data', () => { | ||
// wrapper.update(); | ||
const apiCalls = fetchMock.calls(/rowlevelsecurity\/\?q/); | ||
expect(apiCalls).toHaveLength(1); | ||
expect(apiCalls[0][0]).toMatchInlineSnapshot( | ||
`"http://localhost/api/v1/rowlevelsecurity/?q=(order_column:changed_on_delta_humanized,order_direction:desc,page:0,page_size:25)"`, | ||
); | ||
}); | ||
}); | ||
|
||
describe('RuleList RTL', () => { | ||
async function renderAndWait() { | ||
const mounted = act(async () => { | ||
const mockedProps = {}; | ||
render( | ||
<MemoryRouter> | ||
<QueryParamProvider> | ||
<RowLevelSecurityList {...mockedProps} user={mockUser} /> | ||
</QueryParamProvider> | ||
</MemoryRouter>, | ||
{ useRedux: true }, | ||
); | ||
}); | ||
return mounted; | ||
} | ||
|
||
it('renders add rule button on empty state', async () => { | ||
fetchMock.get( | ||
ruleListEndpoint, | ||
{ result: [], count: 0 }, | ||
{ overwriteRoutes: true }, | ||
); | ||
await renderAndWait(); | ||
|
||
const emptyAddRuleButton = await screen.findByTestId('add-rule-empty'); | ||
expect(emptyAddRuleButton).toBeInTheDocument(); | ||
fetchMock.get( | ||
ruleListEndpoint, | ||
{ result: mockRules, count: 2 }, | ||
{ overwriteRoutes: true }, | ||
); | ||
}); | ||
|
||
it('renders a "Rule" button to add a rule in bulk action', async () => { | ||
await renderAndWait(); | ||
|
||
const addRuleButton = await screen.findByTestId('add-rule'); | ||
const emptyAddRuleButton = screen.queryByTestId('add-rule-empty'); | ||
expect(addRuleButton).toBeInTheDocument(); | ||
expect(emptyAddRuleButton).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('renders filter options', async () => { | ||
await renderAndWait(); | ||
|
||
const searchFilters = screen.queryAllByTestId('filters-search'); | ||
expect(searchFilters).toHaveLength(2); | ||
|
||
const typeFilter = await screen.findByTestId('filters-select'); | ||
expect(typeFilter).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders correct list columns', async () => { | ||
await renderAndWait(); | ||
|
||
const table = screen.getByRole('table'); | ||
expect(table).toBeInTheDocument(); | ||
|
||
const nameColumn = await within(table).findByText('Name'); | ||
const fitlerTypeColumn = await within(table).findByText('Filter Type'); | ||
const groupKeyColumn = await within(table).findByText('Group Key'); | ||
const clauseColumn = await within(table).findByText('Clause'); | ||
const modifiedColumn = await within(table).findByText('Modified'); | ||
const actionsColumn = await within(table).findByText('Actions'); | ||
|
||
expect(nameColumn).toBeInTheDocument(); | ||
expect(fitlerTypeColumn).toBeInTheDocument(); | ||
expect(groupKeyColumn).toBeInTheDocument(); | ||
expect(clauseColumn).toBeInTheDocument(); | ||
expect(modifiedColumn).toBeInTheDocument(); | ||
expect(actionsColumn).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders correct action buttons with write permission', async () => { | ||
await renderAndWait(); | ||
|
||
const deleteActionIcon = screen.queryAllByTestId('rls-list-trash-icon'); | ||
expect(deleteActionIcon).toHaveLength(2); | ||
|
||
const editActionIcon = screen.queryAllByTestId('edit-alt'); | ||
expect(editActionIcon).toHaveLength(2); | ||
}); | ||
|
||
it('should not renders correct action buttons without write permission', async () => { | ||
fetchMock.get( | ||
ruleInfoEndpoint, | ||
{ permissions: ['can_read'] }, | ||
{ overwriteRoutes: true }, | ||
); | ||
|
||
await renderAndWait(); | ||
|
||
const deleteActionIcon = screen.queryByTestId('rls-list-trash-icon'); | ||
expect(deleteActionIcon).not.toBeInTheDocument(); | ||
|
||
const editActionIcon = screen.queryByTestId('edit-alt'); | ||
expect(editActionIcon).not.toBeInTheDocument(); | ||
|
||
fetchMock.get( | ||
ruleInfoEndpoint, | ||
{ permissions: ['can_read', 'can_write'] }, | ||
{ overwriteRoutes: true }, | ||
); | ||
}); | ||
|
||
it('renders popover on new clicking rule button', async () => { | ||
await renderAndWait(); | ||
|
||
const modal = screen.queryByTestId('rls-modal-title'); | ||
expect(modal).not.toBeInTheDocument(); | ||
|
||
const addRuleButton = await screen.findByTestId('add-rule'); | ||
userEvent.click(addRuleButton); | ||
|
||
const modalAfterClick = screen.queryByTestId('rls-modal-title'); | ||
expect(modalAfterClick).toBeInTheDocument(); | ||
}); | ||
}); |
Oops, something went wrong.