diff --git a/.cypress/integration/2_notebooks.spec.js b/.cypress/integration/2_notebooks.spec.js index c73863dce..46aab9b51 100644 --- a/.cypress/integration/2_notebooks.spec.js +++ b/.cypress/integration/2_notebooks.spec.js @@ -21,6 +21,8 @@ import { SAMPLE_PANEL } from '../utils/panel_constants'; import { skipOn } from '@cypress/skip-test'; +import { v4 as uuid4 } from 'uuid'; + const moveToEventsHome = () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-logs#/`); }; @@ -157,7 +159,7 @@ describe('Test reporting integration if plugin installed', () => { beforeEach(() => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-notebooks#/`); cy.get('.euiTableCellContent').contains(TEST_NOTEBOOK).click(); - cy.wait(delay);//page needs to process before checking + cy.wait(delay); //page needs to process before checking cy.get('body').then(($body) => { skipOn($body.find('#reportingActionsButton').length <= 0); }); @@ -290,8 +292,9 @@ describe('Testing paragraphs', () => { it('Adds a SQL query paragraph', () => { cy.contains('Add paragraph').click(); - cy.get('.euiContextMenuItem__text').contains('Code block').click(), { timeout: COMMAND_TIMEOUT_LONG }; - cy.wait(delay);//SQL_QUERY_TEXT will sometimes fail to type without this delay + cy.get('.euiContextMenuItem__text').contains('Code block').click(), + { timeout: COMMAND_TIMEOUT_LONG }; + cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay cy.get('.euiTextArea').type(SQL_QUERY_TEXT); cy.get('.euiButton__text').contains('Run').click(); @@ -301,6 +304,45 @@ describe('Testing paragraphs', () => { cy.get('.euiDataGrid__overflow').should('exist'); }); + it('Renders very long markdown as wrapped', () => { + cy.contains('Add paragraph').click(); + cy.get('.euiContextMenuItem__text').contains('Code block').click(), + { timeout: COMMAND_TIMEOUT_LONG }; + cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay + + const testWord = uuid4().replace(/-/gi, '').repeat(10); + cy.get('.euiTextArea').type(`%md\n${testWord}`); + cy.get('.euiButton__text').contains('Run').click(); + + cy.get('p') + .contains(testWord) + .then((element) => { + const clientWidth = element[0].clientWidth; + const scrollWidth = element[0].scrollWidth; + console.log('paragraph', { clientWidth, scrollWidth }); + expect(scrollWidth, 'Output Text has not been wrapped').to.be.at.most(clientWidth); + }); + }); + + it('Renders very long query as wrapped', () => { + cy.contains('Add paragraph').click(); + cy.get('.euiContextMenuItem__text').contains('Code block').click(), + { timeout: COMMAND_TIMEOUT_LONG }; + cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay + + const testWord = uuid4().replace(/-/gi, '').repeat(10); + cy.get('.euiTextArea').type(`%sql\nSELECT 1 AS ${testWord}`); + cy.get('.euiButton__text').contains('Run').click(); + + cy.get('b') + .contains(testWord) + .then((element) => { + const clientWidth = element[0].clientWidth; + const scrollWidth = element[0].scrollWidth; + expect(scrollWidth, 'Output Text has not been wrapped').to.be.at.most(clientWidth); + }); + }); + it('Adds an observability visualization paragraph', () => { cy.contains('Add paragraph').click(); cy.get('.euiContextMenuItem__text').contains('Visualization').click(); @@ -319,8 +361,9 @@ describe('Testing paragraphs', () => { it('Adds a PPL query paragraph', () => { cy.contains('Add paragraph').click(); - cy.get('.euiContextMenuItem__text').contains('Code block').click(), { timeout: COMMAND_TIMEOUT_LONG };; - cy.wait(delay);//PPL_QUERY_TEXT will sometimes fail to type without this delay + cy.get('.euiContextMenuItem__text').contains('Code block').click(), + { timeout: COMMAND_TIMEOUT_LONG }; + cy.wait(delay); //PPL_QUERY_TEXT will sometimes fail to type without this delay cy.get('.euiTextArea').type(PPL_QUERY_TEXT); cy.get('.euiButton__text').contains('Run').click(); @@ -433,7 +476,7 @@ describe('clean up all test data', () => { cy.get('.euiButton__text').contains('Actions').trigger('mouseover').click(); cy.get('.euiContextMenuItem__text').contains('Delete').trigger('mouseover').click(); cy.get('button.euiButton--danger').should('be.disabled'); - cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', {delay: 50, }); + cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50 }); cy.get('button.euiButton--danger').should('not.be.disabled'); cy.get('.euiButton__text').contains('Delete').trigger('mouseover').click(); cy.get('.euiTextAlign').contains('No Queries or Visualizations').should('exist'); @@ -445,8 +488,8 @@ describe('clean up all test data', () => { cy.get('.euiButton__text').contains('Actions').trigger('mouseover').click(); cy.get('.euiContextMenuItem__text').contains('Delete').trigger('mouseover').click(); cy.get('button.euiButton--danger').should('be.disabled'); - cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50, }); + cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50 }); cy.get('button.euiButton--danger').should('not.be.disabled'); cy.get('.euiButton__text').contains('Delete').trigger('mouseover').click(); }); -}); \ No newline at end of file +}); diff --git a/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/para_output.test.tsx.snap b/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/para_output.test.tsx.snap index a56281a10..a149d56be 100644 --- a/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/para_output.test.tsx.snap +++ b/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/para_output.test.tsx.snap @@ -2,7 +2,7 @@ exports[` spec renders markdown outputs 1`] = `
spec renders other types of outputs 1`] = ` exports[` spec renders query outputs 1`] = `
select * from opensearch_dashboards_sample_data_flights limit 2 diff --git a/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/paragraphs.test.tsx.snap b/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/paragraphs.test.tsx.snap index 0fb456810..bc5be1116 100644 --- a/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/paragraphs.test.tsx.snap +++ b/public/components/notebooks/components/paragraph_components/__tests__/__snapshots__/paragraphs.test.tsx.snap @@ -275,7 +275,7 @@ exports[` spec renders the component 1`] = ` style="opacity: 1; padding: 15px;" >
{ const createQueryColumns = (jsonColumns: any[]) => { let index = 0; - let datagridColumns = []; + const datagridColumns = []; for (index = 0; index < jsonColumns.length; ++index) { const datagridColumnObject = { id: jsonColumns[index].name, @@ -54,7 +54,7 @@ export const ParaOutput = (props: { let index = 0; let schemaIndex = 0; for (index = 0; index < queryObject.datarows.length; ++index) { - let datarowValue = {}; + const datarowValue = {}; for (schemaIndex = 0; schemaIndex < queryObject.schema.length; ++schemaIndex) { const columnName = queryObject.schema[schemaIndex].name; if (typeof queryObject.datarows[index][schemaIndex] === 'object') { @@ -70,7 +70,34 @@ export const ParaOutput = (props: { return data; }; - const outputBody = (key: string, typeOut: string, val: string) => { + const QueryOutput = ({ typeOut, val }: { typeOut: string; val: string }) => { + const inputQuery = para.inp.substring(4, para.inp.length); + const queryObject = JSON.parse(val); + const columns = createQueryColumns(queryObject.schema); + const data = getQueryOutputData(queryObject); + const [visibleColumns, setVisibleColumns] = useState(() => columns.map(({ id }) => id)); + if (queryObject.hasOwnProperty('error')) { + return {val}; + } else { + return ( +
+ + {inputQuery} + + + +
+ ); + } + }; + + const OutputBody = ({ typeOut, val }: { typeOut: string; val: string }) => { /* Returns a component to render paragraph outputs using the para.typeOut property * Currently supports HTML, TABLE, IMG * TODO: add table rendering @@ -80,34 +107,10 @@ export const ParaOutput = (props: { if (typeOut !== undefined) { switch (typeOut) { case 'QUERY': - const inputQuery = para.inp.substring(4, para.inp.length); - const queryObject = JSON.parse(val); - if (queryObject.hasOwnProperty('error')) { - return {val}; - } else { - const columns = createQueryColumns(queryObject.schema); - const data = getQueryOutputData(queryObject); - const [visibleColumns, setVisibleColumns] = useState(() => columns.map(({ id }) => id)); - return ( -
- - {inputQuery} - - - -
- ); - } + return ; case 'MARKDOWN': return ( - + ); @@ -121,11 +124,7 @@ export const ParaOutput = (props: { {`${from} - ${to}`} - + ); case 'OBSERVABILITY_VISUALIZATION': @@ -160,17 +159,17 @@ export const ParaOutput = (props: { ); case 'HTML': return ( - + {/* eslint-disable-next-line react/jsx-pascal-case */} ); case 'TABLE': - return
{val}
; + return
{val}
; case 'IMG': - return ; + return ; default: - return
{val}
; + return
{val}
; } } else { console.log('output not supported', typeOut); @@ -183,7 +182,13 @@ export const ParaOutput = (props: { return !para.isOutputHidden ? ( <> {para.typeOut.map((typeOut: string, tIdx: number) => { - return outputBody(para.uniqueId + '_paraOutputBody', typeOut, para.out[tIdx]); + return ( + + ); })} ) : null; diff --git a/public/components/notebooks/components/paragraph_components/paragraphs.tsx b/public/components/notebooks/components/paragraph_components/paragraphs.tsx index 333cb90de..3b8ac0e6d 100644 --- a/public/components/notebooks/components/paragraph_components/paragraphs.tsx +++ b/public/components/notebooks/components/paragraph_components/paragraphs.tsx @@ -258,7 +258,6 @@ export const Paragraphs = forwardRef((props: ParagraphProps, ref) => {