CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
13k stars 3.5k forks source link

Closes #12278 - added filtering #12279

Closed MNPCMW6444 closed 1 day ago

MNPCMW6444 commented 3 weeks ago

Description

Issue number and link

https://github.com/CesiumGS/cesium/issues/12278 issue #12278

Testing plan

Author checklist

github-actions[bot] commented 3 weeks ago

Thank you for the pull request, @MNPCMW6444! Welcome to the Cesium community!

In order for us to review your PR, please complete the following steps:

Review Pull Request Guidelines to make sure your PR gets accepted quickly.

ggetz commented 2 weeks ago

Thanks for the PR @MNPCMW6444!

I can confirm we have a CLA on file for you.

MNPCMW6444 commented 1 week ago

Could you please add a unit test to verify this fix?

@ggetz Thanks for your CR! For the purpose of determing what characters are problematic (turns out not all control chars) and TESTING after the patch I added a full test to sandcastle. but I didn't commit it to PR because I don't think we want it in the sandcastle. you can see it here - https://github.com/MNPCMW6444/cesium/tree/control-characters-in-labels-causes-the-render-to-stop-%2312278-with-full-test tell me if you still think I need a unit test or any other comment.

ggetz commented 1 week ago

Hi @MNPCMW6444,

For the purpose of determing what characters are problematic (turns out not all control chars) and TESTING after the patch I added a full test to sandcastle. but I didn't commit it to PR because I don't think we want it in the sandcastle.

We want to make sure there is some kind of repeatable test in place so we can 1) ensure the code is correct, and 2) keep this bug from happening again if the code ever changes. Most of the time, we use unit tests to validate functionality like this (rather than Sandcastle, as you mentioned) as we can run it as part of our CI process.

See the Testing Guide for more information, but for this particular case, I think we want to:

  1. Architect the code so it can be easily tested: In this case I would move filterUnsupportedCharacters to a static function that can be accessed outside of the LabelCollection.js file. If we move it to Label.js like I suggested above, then this would look like:
    /**
    * Removes control characters, which will cause an error when rendering a glyph.
    * @private
    * @param {string} text The original label text
    * @returns {string} The renderable filtered text
    */
    Label.filterUnsupportedCharacters = function (text) {
    ...
    }
  2. Create unit tests for filterUnsupportedCharacters: Add a new set of unit tests to LabelCollectionSpec.js. The sandcastle code you linked to included some great test cases you should be able to re-use! For example:
    it("filterUnsupportedCharacters removes emoji characters from text", function () {
    const text = "a😀b";
    const expectedText = "ab";
    expect(Label.filterUnsupportedCharacters(text)).toEqual(expectedText);
    });
  3. Add a label unit test: Finally, we should add one test to LabelCollectionSpec.js to ensure the filtering is happening. Since the tests from step 2 should validate the details of the filterUnsupportedCharacters function, this test can be relatively simple, i.e.:

    it("filters unsupported characters from label text", function () {
    const text = "my\u200btest\u001Dstring😀";
    const expectedText = "myteststring";
    const label = labels.add({
    text: text,
    });
    
    expect(label.text).toEqual(text);
    expect(label._renderedText).toEqual(expectedText);
    });

What do you think? Could you give it a try?

MNPCMW6444 commented 6 days ago

so i will make the regex simpler with a unicode range and apply it in Label.js, anc create a unit test one thing im not sure, @ggetz if its a private static method Label.filterUnsupportedCharacters = function (text) { can the set of text access it? how?

ggetz commented 4 days ago

if its a private static method Label.filterUnsupportedCharacters = function (text) { can the set of text access it? how?

@MNPCMW6444 Good question! The private tag here affects the generated documentation and generated typescript definitions for the function. It will exclude Label.filterUnsupportedCharacters from the API reference doc and the library typescript definitions, with the intention that Label.filterUnsupportedCharacters will bot be used directly by end users of the library.

It can, however, still be used within the codebase itself, such as inside of the text set function. It can also be used in the unit tests to verify the functionality.

MNPCMW6444 commented 2 days ago

ok, i pushed the new solution @ggetz thanks

ggetz commented 1 day ago

Thanks for the updates @MNPCMW6444! This is looking good!

I pushed two small tweaks:

  1. Incorporate a previously existing filtering rule into filterUnsupportedCharacters
  2. Ensure \t, \n, and \r characters were being honored.
MNPCMW6444 commented 1 day ago

whats the next step @ggetz

MNPCMW6444 commented 1 day ago

whats the next step @ggetz