From 233daa3ff5945dafe1128897ded23dcb5705a2ae Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Mon, 22 Aug 2022 13:50:15 -0500 Subject: [PATCH 1/9] Fixed double quotes copy and paste bug --- .../dash-table/utils/TableClipboardHelper.ts | 11 ++++++- .../tests/selenium/test_basic_copy_paste.py | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts index ce9eddc69e..38ab4174f7 100644 --- a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts +++ b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts @@ -98,7 +98,7 @@ export default class TableClipboardHelper { ? TableClipboardHelper.localCopyWithoutHeaders : TableClipboardHelper.lastLocalCopy; const values = - localDf === text ? localCopy : SheetClip.prototype.parse(text); + localDf === text ? localCopy : TableClipboardHelper.parse(text); return applyClipboardToData( values, @@ -111,4 +111,13 @@ export default class TableClipboardHelper { overflowRows ); } + + private static parse(str: string) { + const temprows = str.split('\n'); + if (temprows.length > 1 && temprows[temprows.length - 1] === '') { + temprows.pop(); + } + const rows = temprows.map(row => row.split('\t')); + return rows; + } } diff --git a/components/dash-table/tests/selenium/test_basic_copy_paste.py b/components/dash-table/tests/selenium/test_basic_copy_paste.py index 813b36a6a7..0f3adb8d03 100644 --- a/components/dash-table/tests/selenium/test_basic_copy_paste.py +++ b/components/dash-table/tests/selenium/test_basic_copy_paste.py @@ -51,6 +51,17 @@ def get_app(): cell_selectable=False, sort_action="native", ), + DataTable( + id="table4", + data=[{"string": 'a""b', "int": 10}, {"string": "hello", "int": 11}], + columns=[ + {"name": "string", "id": "string"}, + {"name": "int", "id": "int"}, + ], + editable=True, + sort_action="native", + include_headers_on_copy_paste=True, + ), ] ) @@ -334,3 +345,23 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): assert target.cell(1, 1).get_text() == source.cell(2, 2).get_text() assert test.get_log_errors() == [] + +def test_tbcp011_copy_double_quotes(test): + test.start_server(get_app()) + + source = test.table("table4") + target = test.table("table2") + + source.cell(0, 0).click() + with test.hold(Keys.SHIFT): + source.cell(0, 1).click() + + test.copy() + target.cell(0, 0).click() + test.paste() + + for row in range(1): + for col in range(2): + assert target.cell(row, col).get_text() == source.cell(row, col).get_text() + + assert test.get_log_errors() == [] From f38dfb2689d9627ddd6fee7bcd6a9b960286bea9 Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Mon, 22 Aug 2022 14:25:55 -0500 Subject: [PATCH 2/9] Fixed lint error --- components/dash-table/tests/selenium/test_basic_copy_paste.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/dash-table/tests/selenium/test_basic_copy_paste.py b/components/dash-table/tests/selenium/test_basic_copy_paste.py index 0f3adb8d03..658559516d 100644 --- a/components/dash-table/tests/selenium/test_basic_copy_paste.py +++ b/components/dash-table/tests/selenium/test_basic_copy_paste.py @@ -346,6 +346,7 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): assert test.get_log_errors() == [] + def test_tbcp011_copy_double_quotes(test): test.start_server(get_app()) From 12377d9b9455bd0c2492264c664d36a5129266e2 Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Mon, 22 Aug 2022 15:01:34 -0500 Subject: [PATCH 3/9] Retrying tests From 711360c633cf696dd911683e7b4201becbc05c9e Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Thu, 1 Sep 2022 10:49:37 -0500 Subject: [PATCH 4/9] Fix double quote bug while allowing multiline cells --- .../dash-table/utils/TableClipboardHelper.ts | 58 +++++++++++++++++-- .../js-unit/table_clipboard_helper_test.ts | 49 ++++++++++++++++ .../tests/selenium/test_basic_copy_paste.py | 48 ++++++++++++++- 3 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 components/dash-table/tests/js-unit/table_clipboard_helper_test.ts diff --git a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts index 38ab4174f7..008d915e47 100644 --- a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts +++ b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts @@ -113,11 +113,59 @@ export default class TableClipboardHelper { } private static parse(str: string) { - const temprows = str.split('\n'); - if (temprows.length > 1 && temprows[temprows.length - 1] === '') { - temprows.pop(); + let r, + rlen, + a = 0, + c, + clen, + multiline, + last, + arr: string[][] = [[]]; + const rows = str.split('\n'); + if (rows.length > 1 && rows[rows.length - 1] === '') { + rows.pop(); } - const rows = temprows.map(row => row.split('\t')); - return rows; + arr = []; + for (r = 0, rlen = rows.length; r < rlen; r += 1) { + const row = rows[r].split('\t'); + for (c = 0, clen = row.length; c < clen; c += 1) { + if (!arr[a]) { + arr[a] = []; + } + if (multiline && c === 0) { + last = arr[a].length - 1; + arr[a][last] = arr[a][last] + '\n' + row[0]; + if ( + multiline && + TableClipboardHelper.countQuotes(row[0]) & 1 + ) { + multiline = false; + arr[a][last] = arr[a][last] + .substring(0, arr[a][last].length - 1) + .replace(/""/g, '"'); + } + } else { + if ( + c === clen - 1 && + row[c].indexOf('"') === 0 && + TableClipboardHelper.countQuotes(row[c]) & 1 + ) { + arr[a].push(row[c].substring(1).replace(/""/g, '"')); + multiline = true; + } else { + arr[a].push(row[c]); + multiline = false; + } + } + } + if (!multiline) { + a += 1; + } + } + return arr; + } + + private static countQuotes(str: string) { + return str.split('"').length - 1; } } diff --git a/components/dash-table/tests/js-unit/table_clipboard_helper_test.ts b/components/dash-table/tests/js-unit/table_clipboard_helper_test.ts new file mode 100644 index 0000000000..442c1f695a --- /dev/null +++ b/components/dash-table/tests/js-unit/table_clipboard_helper_test.ts @@ -0,0 +1,49 @@ +import {expect} from 'chai'; + +import TableClipboardHelper from 'dash-table/utils/TableClipboardHelper'; + +describe('table clipboard helper tests', () => { + it('test parse basic', () => { + const res = TableClipboardHelper.parse('abc\tefg\n123\t456'); + expect(res.length).to.equal(2); + expect(res[0].length).to.equal(2); + expect(res[1].length).to.equal(2); + expect(res[0][0]).to.equal('abc'); + expect(res[0][1]).to.equal('efg'); + expect(res[1][0]).to.equal('123'); + expect(res[1][1]).to.equal('456'); + }); + + it('test parse with double quotes', () => { + const res = TableClipboardHelper.parse('a""bc\tefg\n123\t456'); + expect(res.length).to.equal(2); + expect(res[0].length).to.equal(2); + expect(res[1].length).to.equal(2); + expect(res[0][0]).to.equal('a""bc'); + expect(res[0][1]).to.equal('efg'); + expect(res[1][0]).to.equal('123'); + expect(res[1][1]).to.equal('456'); + }); + + it('test with multiline', () => { + const res = TableClipboardHelper.parse('"a\nb\nc"\tefg\n123\t456'); + expect(res.length).to.equal(2); + expect(res[0].length).to.equal(2); + expect(res[1].length).to.equal(2); + expect(res[0][0]).to.equal('a\nb\nc'); + expect(res[0][1]).to.equal('efg'); + expect(res[1][0]).to.equal('123'); + expect(res[1][1]).to.equal('456'); + }); + + it('test with multiline and double quotes', () => { + const res = TableClipboardHelper.parse('"a\nb""c"\te""fg\n123\t456'); + expect(res.length).to.equal(2); + expect(res[0].length).to.equal(2); + expect(res[1].length).to.equal(2); + expect(res[0][0]).to.equal('a\nb"c'); + expect(res[0][1]).to.equal('e""fg'); + expect(res[1][0]).to.equal('123'); + expect(res[1][1]).to.equal('456'); + }); +}); diff --git a/components/dash-table/tests/selenium/test_basic_copy_paste.py b/components/dash-table/tests/selenium/test_basic_copy_paste.py index 658559516d..0303164ea5 100644 --- a/components/dash-table/tests/selenium/test_basic_copy_paste.py +++ b/components/dash-table/tests/selenium/test_basic_copy_paste.py @@ -53,7 +53,10 @@ def get_app(): ), DataTable( id="table4", - data=[{"string": 'a""b', "int": 10}, {"string": "hello", "int": 11}], + data=[ + {"string": 'a""b', "int": 10}, + {"string": 'hello\n""hi', "int": 11}, + ], columns=[ {"name": "string", "id": "string"}, {"name": "int", "id": "int"}, @@ -182,8 +185,12 @@ def test_tbcp004_copy_9_and_10(test): ActionChains(test.driver).send_keys(Keys.DOWN).perform() test.copy() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -311,8 +318,12 @@ def test_tbcp009_copy_9_and_10_click(test): source.cell(10, 0).click() test.copy() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -333,8 +344,10 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): source.cell(2, 2).double_click() assert source.cell(2, 2).get_text() == test.get_selected_text() - # copy the source text to clipboard using CTRL+C + # copy the source text to clipboard using CTRL+C or COMMAND+C test.copy() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("c").perform() # assert the target cell value is different before paste target.cell(1, 1).click() @@ -342,6 +355,8 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): # assert the target cell value has changed to the pasted value test.paste() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("v").perform() assert target.cell(1, 1).get_text() == source.cell(2, 2).get_text() assert test.get_log_errors() == [] @@ -358,11 +373,40 @@ def test_tbcp011_copy_double_quotes(test): source.cell(0, 1).click() test.copy() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("v").perform() for row in range(1): for col in range(2): assert target.cell(row, col).get_text() == source.cell(row, col).get_text() assert test.get_log_errors() == [] + + +def test_tbcp011_copy_multiline(test): + test.start_server(get_app()) + + source = test.table("table4") + target = test.table("table2") + + source.cell(1, 0).click() + with test.hold(Keys.SHIFT): + source.cell(1, 1).click() + + test.copy() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("c").perform() + target.cell(1, 0).click() + test.paste() + with test.hold(Keys.COMMAND): + ActionChains(test.driver).send_keys("v").perform() + + for row in range(1, 2): + for col in range(2): + assert target.cell(row, col).get_text() == source.cell(row, col).get_text() + + assert test.get_log_errors() == [] From 2373e424ad18ec6dd59fd9c45f14a1b68bd52d5a Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Thu, 1 Sep 2022 11:47:31 -0500 Subject: [PATCH 5/9] Small logical fix --- .../src/dash-table/utils/TableClipboardHelper.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts index 008d915e47..b1f1be71a5 100644 --- a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts +++ b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts @@ -85,6 +85,7 @@ export default class TableClipboardHelper { includeHeaders: boolean ): {data: Data; columns: Columns} | void { const text = Clipboard.get(ev); + console.log(text); Logger.trace('TableClipboard -- get clipboard data: ', text); if (!text) { @@ -134,15 +135,17 @@ export default class TableClipboardHelper { } if (multiline && c === 0) { last = arr[a].length - 1; - arr[a][last] = arr[a][last] + '\n' + row[0]; + arr[a][last] = + arr[a][last] + '\n' + row[0].replace(/""/g, '"'); if ( multiline && TableClipboardHelper.countQuotes(row[0]) & 1 ) { multiline = false; - arr[a][last] = arr[a][last] - .substring(0, arr[a][last].length - 1) - .replace(/""/g, '"'); + arr[a][last] = arr[a][last].substring( + 0, + arr[a][last].length - 1 + ); } } else { if ( From 7f2633670adee0b0ebac1ab867291d5242c56635 Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Thu, 1 Sep 2022 12:36:31 -0500 Subject: [PATCH 6/9] Fix selenium test error --- .../tests/selenium/test_basic_copy_paste.py | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/components/dash-table/tests/selenium/test_basic_copy_paste.py b/components/dash-table/tests/selenium/test_basic_copy_paste.py index 0303164ea5..bf8620b4ef 100644 --- a/components/dash-table/tests/selenium/test_basic_copy_paste.py +++ b/components/dash-table/tests/selenium/test_basic_copy_paste.py @@ -185,12 +185,14 @@ def test_tbcp004_copy_9_and_10(test): ActionChains(test.driver).send_keys(Keys.DOWN).perform() test.copy() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("c").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("v").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -318,12 +320,14 @@ def test_tbcp009_copy_9_and_10_click(test): source.cell(10, 0).click() test.copy() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("c").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("v").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -346,8 +350,9 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): # copy the source text to clipboard using CTRL+C or COMMAND+C test.copy() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("c").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("c").perform() # assert the target cell value is different before paste target.cell(1, 1).click() @@ -355,8 +360,9 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): # assert the target cell value has changed to the pasted value test.paste() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("v").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("v").perform() assert target.cell(1, 1).get_text() == source.cell(2, 2).get_text() assert test.get_log_errors() == [] @@ -373,12 +379,14 @@ def test_tbcp011_copy_double_quotes(test): source.cell(0, 1).click() test.copy() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("c").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("v").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("v").perform() for row in range(1): for col in range(2): @@ -398,12 +406,14 @@ def test_tbcp011_copy_multiline(test): source.cell(1, 1).click() test.copy() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("c").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("c").perform() target.cell(1, 0).click() test.paste() - with test.hold(Keys.COMMAND): - ActionChains(test.driver).send_keys("v").perform() + # Uncomment the following two lines if using a Mac computer + # with test.hold(Keys.COMMAND): + # ActionChains(test.driver).send_keys("v").perform() for row in range(1, 2): for col in range(2): From ce9b09d0305b70d0307db9b7bb94e600a0c1cad4 Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Tue, 6 Sep 2022 10:07:28 -0500 Subject: [PATCH 7/9] Small fixes --- .../dash-table/utils/TableClipboardHelper.ts | 1 - .../dash-table/tests/selenium/conftest.py | 7 ++--- .../tests/selenium/test_basic_copy_paste.py | 30 ------------------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts index b1f1be71a5..a6682bb43e 100644 --- a/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts +++ b/components/dash-table/src/dash-table/utils/TableClipboardHelper.ts @@ -85,7 +85,6 @@ export default class TableClipboardHelper { includeHeaders: boolean ): {data: Data; columns: Columns} | void { const text = Clipboard.get(ev); - console.log(text); Logger.trace('TableClipboard -- get clipboard data: ', text); if (!text) { diff --git a/components/dash-table/tests/selenium/conftest.py b/components/dash-table/tests/selenium/conftest.py index 5be45ce543..19648bd0b9 100644 --- a/components/dash-table/tests/selenium/conftest.py +++ b/components/dash-table/tests/selenium/conftest.py @@ -26,6 +26,7 @@ _ANY = ".dash-spreadsheet" _TIMEOUT = 10 +CMD = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL class HoldKeyContext: @preconditions(_validate_mixin, _validate_key) @@ -268,8 +269,6 @@ def filter(self): ) def filter_clear(self): - CMD = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL - self.filter().find_element(By.CSS_SELECTOR, "input").click() ac = ActionChains(self.mixin.driver) ac.key_down(CMD) @@ -518,11 +517,11 @@ def get_table_ids(self): ) def copy(self): - with self.hold(Keys.CONTROL): + with self.hold(CMD): self.send_keys("c") def paste(self): - with self.hold(Keys.CONTROL): + with self.hold(CMD): self.send_keys("v") @preconditions(_validate_key) diff --git a/components/dash-table/tests/selenium/test_basic_copy_paste.py b/components/dash-table/tests/selenium/test_basic_copy_paste.py index bf8620b4ef..10076cc97e 100644 --- a/components/dash-table/tests/selenium/test_basic_copy_paste.py +++ b/components/dash-table/tests/selenium/test_basic_copy_paste.py @@ -185,14 +185,8 @@ def test_tbcp004_copy_9_and_10(test): ActionChains(test.driver).send_keys(Keys.DOWN).perform() test.copy() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -320,14 +314,8 @@ def test_tbcp009_copy_9_and_10_click(test): source.cell(10, 0).click() test.copy() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("v").perform() for row in range(2): for col in range(1): @@ -350,9 +338,6 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): # copy the source text to clipboard using CTRL+C or COMMAND+C test.copy() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("c").perform() # assert the target cell value is different before paste target.cell(1, 1).click() @@ -360,9 +345,6 @@ def test_tbcp010_copy_from_unselectable_cells_table(test): # assert the target cell value has changed to the pasted value test.paste() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("v").perform() assert target.cell(1, 1).get_text() == source.cell(2, 2).get_text() assert test.get_log_errors() == [] @@ -379,14 +361,8 @@ def test_tbcp011_copy_double_quotes(test): source.cell(0, 1).click() test.copy() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("c").perform() target.cell(0, 0).click() test.paste() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("v").perform() for row in range(1): for col in range(2): @@ -406,14 +382,8 @@ def test_tbcp011_copy_multiline(test): source.cell(1, 1).click() test.copy() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("c").perform() target.cell(1, 0).click() test.paste() - # Uncomment the following two lines if using a Mac computer - # with test.hold(Keys.COMMAND): - # ActionChains(test.driver).send_keys("v").perform() for row in range(1, 2): for col in range(2): From efe8c7e8187314a91720f3683e0e4713ddae95ca Mon Sep 17 00:00:00 2001 From: Amy Morrill Date: Tue, 6 Sep 2022 10:47:30 -0500 Subject: [PATCH 8/9] Lint fix --- components/dash-table/tests/selenium/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/dash-table/tests/selenium/conftest.py b/components/dash-table/tests/selenium/conftest.py index 19648bd0b9..a171c681cc 100644 --- a/components/dash-table/tests/selenium/conftest.py +++ b/components/dash-table/tests/selenium/conftest.py @@ -26,7 +26,8 @@ _ANY = ".dash-spreadsheet" _TIMEOUT = 10 -CMD = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL +CMD = Keys.COMMAND if platform.system() == "Darwin" else Keys.CONTROL + class HoldKeyContext: @preconditions(_validate_mixin, _validate_key) From 5c73fabd778e2f03b1375614c165d748b6302813 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Wed, 7 Sep 2022 19:15:13 -0400 Subject: [PATCH 9/9] changelog for #2202 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54bb6d4df9..3eccf04b3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#2152](https://github.com/plotly/dash/pull/2152) Fix bug [#2128](https://github.com/plotly/dash/issues/2128) preventing rendering of multiple components inside a dictionary. - [#2187](https://github.com/plotly/dash/pull/2187) Fix confusing error message when trying to use pytest fixtures but `dash[testing]` is not installed. +- [#2202](https://github.com/plotly/dash/pull/2202) Fix bug [#2185](https://github.com/plotly/dash/issues/2185) when you copy text with multiple quotes into a table ## [2.6.1] - 2022-08-01